J
James W. Mills
Hello list.
I need to use multicast in a project I am working on. I would like to
have a multicast sender send a large amount of multicast data, and a
multicast receiver receive it.
I used the example I found here:
http://onestepback.org/index.cgi/Tech/Ruby/MulticastingInRuby.red
to get started.
What I want initially is to be able to blast packets to a multicast
group. I wrote a simple multicast sender that prints a message every
(almost) MB of data it sends. I also wrote a simple receiver that does
the same thing for every (almost) MB of data it receives. Here they are.
Sender:
##############################
require 'socket'
MULTICAST_ADDR = "225.0.0.1"
PORT= 1200
begin
socket = UDPSocket.open
socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, [1].pack('i'))
data_source = File.open '/dev/zero'
data_length = 0
loop do
data = data_source.read(1024)
data_length += data.length
if (data_length % 102400) == 0
puts data_length
end
socket.send(data, 0, MULTICAST_ADDR, PORT)
end
ensure
socket.close
end
##############################
Receiver:
##############################
require 'socket'
require 'ipaddr'
MULTICAST_ADDR = "225.0.0.1"
PORT = 1200
ip = IPAddr.new(MULTICAST_ADDR).hton + IPAddr.new("0.0.0.0").hton
sock = UDPSocket.new
sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ip)
sock.bind(Socket::INADDR_ANY, PORT)
start = Time.now
data_length = 0
begin
while true
msg, info = sock.recvfrom(1024)
data_length += msg.length
if data_length % 102400 == 0
puts data_length
end
end
ensure
sock.close
puts "Ran for #{Time.now - start}"
end
##############################
If you start the receiver, then start the sender, you will see that the
numbers do not line up at all. The receiver gets one MB for every 10 or
so MB that is sent.
Now, please don't fillet me over the coals for this, but I have the
receiver written in perl as well. The perl code does the same thing as
the Ruby code was meant to. Here it is.
##############################
use IO::Socket::Multicast;
# create a new UDP socket ready to read datagrams on port 1100
my $s = IO::Socket::Multicast->new(LocalPort=>1200);
# Add a multicast group
$s->mcast_add('225.0.0.1');
# now receive some multicast data
$data = "";
$t=0;
while(true) {
$s->recv($data,1024);
$t += length $data;
if($t % 102400 == 0) {
warn "$t";
}
}
##############################
If you run the perl receiver against the Ruby sender, the programs print
out the same messages, as expected. I am very curious to know what I am
doing wrong with the Ruby receiver that is causing it to miss so much
data. I suspect the line:
sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ip)
in the receiver might hold the answer, but so far nothing I have tried
has made any difference. I find it interesting that it is using TCP
instead of UDP/DGRAM, but I was unable to get it to work with IPPROTO_UDP...
Help is very much appreciated!
Thanks,
~james
I need to use multicast in a project I am working on. I would like to
have a multicast sender send a large amount of multicast data, and a
multicast receiver receive it.
I used the example I found here:
http://onestepback.org/index.cgi/Tech/Ruby/MulticastingInRuby.red
to get started.
What I want initially is to be able to blast packets to a multicast
group. I wrote a simple multicast sender that prints a message every
(almost) MB of data it sends. I also wrote a simple receiver that does
the same thing for every (almost) MB of data it receives. Here they are.
Sender:
##############################
require 'socket'
MULTICAST_ADDR = "225.0.0.1"
PORT= 1200
begin
socket = UDPSocket.open
socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, [1].pack('i'))
data_source = File.open '/dev/zero'
data_length = 0
loop do
data = data_source.read(1024)
data_length += data.length
if (data_length % 102400) == 0
puts data_length
end
socket.send(data, 0, MULTICAST_ADDR, PORT)
end
ensure
socket.close
end
##############################
Receiver:
##############################
require 'socket'
require 'ipaddr'
MULTICAST_ADDR = "225.0.0.1"
PORT = 1200
ip = IPAddr.new(MULTICAST_ADDR).hton + IPAddr.new("0.0.0.0").hton
sock = UDPSocket.new
sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ip)
sock.bind(Socket::INADDR_ANY, PORT)
start = Time.now
data_length = 0
begin
while true
msg, info = sock.recvfrom(1024)
data_length += msg.length
if data_length % 102400 == 0
puts data_length
end
end
ensure
sock.close
puts "Ran for #{Time.now - start}"
end
##############################
If you start the receiver, then start the sender, you will see that the
numbers do not line up at all. The receiver gets one MB for every 10 or
so MB that is sent.
Now, please don't fillet me over the coals for this, but I have the
receiver written in perl as well. The perl code does the same thing as
the Ruby code was meant to. Here it is.
##############################
use IO::Socket::Multicast;
# create a new UDP socket ready to read datagrams on port 1100
my $s = IO::Socket::Multicast->new(LocalPort=>1200);
# Add a multicast group
$s->mcast_add('225.0.0.1');
# now receive some multicast data
$data = "";
$t=0;
while(true) {
$s->recv($data,1024);
$t += length $data;
if($t % 102400 == 0) {
warn "$t";
}
}
##############################
If you run the perl receiver against the Ruby sender, the programs print
out the same messages, as expected. I am very curious to know what I am
doing wrong with the Ruby receiver that is causing it to miss so much
data. I suspect the line:
sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ip)
in the receiver might hold the answer, but so far nothing I have tried
has made any difference. I find it interesting that it is using TCP
instead of UDP/DGRAM, but I was unable to get it to work with IPPROTO_UDP...
Help is very much appreciated!
Thanks,
~james