A while back I asked:
> 2. One thing I need to do is implement a discovery protocol, involving a
> UDP broadcast. I don't see a way to set SO_BROADCAST on the underlying
> socket. Is there any way to do that?
Francis replied:
> For UDP broadcasts, just sent the packet to a target address of
> 255.255.255.255 to get a broadcast on your local lan.
I wrote test code (see below) to try this.
Using the Ruby UDPSocket class:
bc_sock ==>
"hello sock world" -> 255.255.255.255">1392 255.255.255.255
sent
... and the server (running separately) gets it:
serv ==>
udp server 1392
129.196.215.84">1628 129.196.215.84 -> "hello sock world"
goodbye
But using EM, it doesn't get to the server:
bc_evma ==>
"hello evma world" -> 255.255.255.255">1392 255.255.255.255
sent
serv ==>
udp server 1392
I assume that the difference is that I set the SO_BROADCAST option in the
Socket-based code. So I reiterate my original question: is there a way to
set the SO_BROADCAST option on the underlying UDP socket resulting from
EM::open_datagram_socket?
Thanks,
Mark Z.
------------------ Test Code ----------------------
require "socket"
require "eventmachine"
PORT = 1392
BROADCAST = "255.255.255.255"
# Broadcast using UDPSocket.
def bc_sock( broadcast_addr = BROADCAST )
s = UDPSocket.new
s.setsockopt( Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1 )
msg = "hello sock world"
puts "#{msg.inspect} -> # #{broadcast_addr}"
s.send( msg, 0, broadcast_addr, PORT )
s.close
puts "sent"
end
# Broadcast using EM, datagram socket, and send_datagram.
def bc_evma( broadcast_addr = BROADCAST )
msg = "hello evma world"
puts "#{msg.inspect} -> # #{broadcast_addr}"
EM::run {
conn = EM::open_datagram_socket( "", 0, Client )
conn.send_datagram( msg, broadcast_addr, PORT )
conn.close_connection_after_writing
}
end
module Client
def unbind
puts "sent"
EM::stop_event_loop
end
end
# Server that receives a datagram and quits.
def serv
s = UDPSocket.new
s.bind( "", PORT )
puts "udp server %d" % [PORT]
msg, sender = s.recvfrom(64)
puts "#{sender[1]} #{sender[3]} -> #{msg.inspect}"
s.close
puts "goodbye"
end
|