12

So, the very simple code that I'm trying to use is here: http://wiki.python.org/moin/UdpCommunication

(also here): Sending:

import socket UDP_IP = "127.0.0.1" UDP_PORT = 5005 MESSAGE = "Hello, World!" print "UDP target IP:", UDP_IP print "UDP target port:", UDP_PORT print "message:", MESSAGE sock = socket.socket(socket.AF_INET, # Internet socket.SOCK_DGRAM) # UDP sock.sendto(MESSAGE, (UDP_IP, UDP_PORT)) 

Receiving:

import socket UDP_IP = "127.0.0.1" UDP_PORT = 5005 sock = socket.socket(socket.AF_INET, # Internet socket.SOCK_DGRAM) # UDP sock.bind((UDP_IP, UDP_PORT)) while True: data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes print "received message:", data 

The code works fine when I run both applications on my computer. I put the sending code on my laptop with:

UDP_IP="IP address for my computer" 

Everything else is the same. Yet, nothing happens. What am I doing incorrectly? I used wireshark and determined that the packet is being sent and received; however, the python program isn't receiving the packet. I'm very confused.

Any help is much appreciated. Thanks in advance.

0

4 Answers 4

18

Try binding to all local interfaces on the receiving side:

sock.bind(("", UDP_PORT)) # could also use "0.0.0.0" 

Note that the behavior of operating systems is not entirely logical (nor consistent) in terms of binding when receiving UDP packets, especially for multicast traffic. This is the behavior you get:

Linux: Binding to a specific IP will filter the incoming UDP packets and only the ones targeted at this specific IP will get through the filter. This means for example that multicast UDP packets received by an interface with IP 192.168.1.100 will not be received when binding to IP 192.168.1.100. On Linux the normal bind does not bind to an interface. Use setsockopt(SO_BINDTODEVICE) for this. Binding to 0.0.0.0 (or "" on Python) will always receive all UDP packets received by the machine on all interfaces, regardless of the destination IP, so this is usually the most useful option on Linux.

Windows: Binding to a specific IP will bind to the interface belonging to this IP, pretty much like setsockopt(SO_BINDTODEVICE) does on Linux. Incoming UDP packets are not filtered by this IP, so multicast traffic can be received even when binding to a concrete IP. (This is probably the first time the Windows behavior seems more consistent to me than the Linux behavior.)

Python does not abstract these OS specific differences away for sockets (as it does in other areas). As long as you have no explicit reason not to do so I suggest to always bind to 0.0.0.0.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your reply. Every option except socket.INADDR_ANY simply did nothing, and socket.INADDR_ANY gave an error saying that it found an int, but expected a string, so I used: sock.bind((str(socket.INADDR_ANY), UDP_PORT)), but this produced: socket.gaierror: [Errno 11004] getaddrinfo failed when I actually tried to connect.
Argh, yes, socket.INADDR_ANY is just mapped to an int which is useless with the Python socket module. I will remove that from the answer. (Of course this does not solve your problem.)
I eventually figured out my issue and it was pretty complex and highly localized, so I'm going to accept your answer, since I think it's probably good advice for most people with my described problem.
7

eventually figured out my issue and it was pretty complex and highly localized,

I had a very similar problem happen to me. I realize that you have already solved this problem, however I thought it would be good to share how I solved the issue for me.

The issue I found was with my firewall settings. I found that the packets were being blocked by Windows Firewall.

I too had used Wireshark which showed that packets were being sent and received. It is important to note that Wireshark grabs packets at a much lower level than a Python application.

By running my code locally with a listener on one port and a client on another port on the same PC, the firewall wasn't blocking the packets. When I moved to interfacing with an external machine, the firewall rules came into play blocking the incoming packets.

Changing the firewall policy fixed this issue. There are numerous ways and inherent security risks to changing the firewall to make this work so I will leave that part up to the IT professionals. :-)

Comments

-1

Make sure that the server port is open while trying to execute recvfrom call. If the destination port from which the socket reading was down then we get this error.

I got the same error and fixed by reading this link - http://www.linuxsa.org.au/mailing-list/2001-04/668.html

1 Comment

Link is broken and answer is confused: Ports can be open on a firewall but this will not affect the recvfrom() call. This is not a firewall issue.
-1

So if I want to send a message AND receive a response then how would the code look? Like this?

import socket UDP_IP = "127.0.0.1" UDP_PORT = 5005 MESSAGE = "Hello, World!" sock = socket.socket(socket.AF_INET, # Internet socket.SOCK_DGRAM) # UDP sock.sendto(MESSAGE, (UDP_IP, UDP_PORT)) sock.bind((UDP_IP, UDP_PORT)) while True: data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes print "received message:", data 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.