Python raw socket listening on UDP packets; only half of the packets received

I am trying to create a raw socket in Python that only listens for UDP packets:

import socket s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP) s.bind(('0.0.0.0', 1337)) while True: print s.recvfrom(65535) 

This needs to be run as root and creates a raw socket on port 1337, which listens for UDP packets and prints them whenever they are received; no problem.

Now let me make a small client to check if this works:

 import socket c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) c.connect(('127.0.0.1', 1337)) c.send('message 1') c.send('message 2') c.send('message 3') c.send('message 4') c.send('message 5') c.send('message 6') 

In sequence, only the first, third and fifth messages ( message 1 , message 3 and message 5 ) will pass and will be printed on the server output. The second, fourth and sixth messages are not displayed on the server output, and instead the client receives an exception:

 >>> c.send('message 2') Traceback (most recent call last): File "<stdin>", line 1, in <module> socket.error: [Errno 111] Connection refused 

Running this in Wireshark shows that it is receiving an ICMP response for "Destination unreachable". I was able to reproduce this on three different machines (although everything works on Linux). Am I missing something? Is this the expected behavior for UDP to drop packets sequentially, since the protocols used must be tolerant of packet loss? However, why packages will be deleted when they are sent via the local interface?

Binding the server to 127.0.0.1 instead of 0.0.0.0 has the same result.

+7
source share
1 answer

Decided it was stupid; please let me know if there is another way and I will change the accepted answer.

The solution is to use two sockets connected to the same port; one raw, one not raw:

 import socket, select s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s1.bind(('0.0.0.0', 1337)) s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP) s2.bind(('0.0.0.0', 1337)) while True: r, w, x = select.select([s1, s2], [], []) for i in r: print i, i.recvfrom(131072) 

This causes the Destination unreachable ICMP packets to leave and all packets go through a fine. I think the operating system wants an uneven socket to listen on the port, so that everything is fine, and then any raw sockets listening on the same port will receive copies of the packets.

+7
source

All Articles