tags:

views:

575

answers:

5

I've written this ruby program to send a UDP Packet to port 16800:

require 'socket'
sock = UDPSocket.new
sock.bind("", 47123) 
sock.send("Hello!", 0, "192.168.0.100", 16800)
sock.close

where 192.168.0.100 is my own ip address. However, the packet doesn't show in Wireshark and my UDP server listening on port 16800 on the same PC (running Linux) isn't receiving anything.

When I slightly rewrite the program to

require 'socket'
sock = UDPSocket.new
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
sock.bind("", 47123) 
sock.send("Hello!", 0, "<broadcast>", 16800)
sock.close

the packet does show up in Wireshark, but my server still isn't receiving anything.

Am I missing something obvious?

EDIT: The server code, for completeness

require 'socket'
sock = UDPSocket.new
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
sock.bind(nil, 16800)
while true
    packet = sock.recvfrom(1024)
    puts packet
end

However, this was copied somewhere from the internet, and while editing it for stackoverflow, i found out that the server always receives packets sent to 127.0.0.1 but when I change nil to "", the server suddenly also receives the packets sent above. Is this a bug in the ruby socket implementation?

A: 

Have you tried sending to "localhost" or "127.0.0.1"? This will send directly to the local computer and will help diagnose the problem further.

Bob Breznak
+1  A: 

UDPSocket.BIND takes a host and a port. Try changing the nil to your IP address. From http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/; use

require 'socket'

def local_ip  
  orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true  # turn off reverse DNS resolution temporarily  

  UDPSocket.open do |s|  
    s.connect '64.233.187.99', 1  
    s.addr.last  
  end  
ensure  
  Socket.do_not_reverse_lookup = orig  
end

to get your IP

choudeshell
A: 

Kind of speculating here, but you might want to consider something like this - when you use the computer's own IP, the packets aren't visible on the physical link b/c the tcp/ip stack doesn't have to push them that far to get them where they are going, it can turn them around internally to the computer at one of the higher layers in that seven-layer stack model (the 'transport' layer, perhaps?)

JustJeff
I think that's an issue only with Windows, and only when you're attempting to sniff packets on 127.0.0.1. At least in my experience.
MattC
+1  A: 

I just used your very code and the problem is you're not binding to a specific IP address. I don't know about Linux but on OS X there's an issue where sometimes the default will attach to an unused IP6 address rather than the interface you were expecting.

Changing "" to 192.168.1.255 on the server, and including "192.168.1.255" on the bind in the client made all this work for me :)

Peter Cooper
A: 

If such a connection is supposed to work, and you see the packages using Wireshark, then you should also check the software firewall on your machine. If it blocks traffic to the UDP port you want to use you can still see the package using Wireshark!

pklaus