Python-raw-socket lauschen auf UDP-Pakete; nur die Hälfte der empfangenen Pakete
Ich versuche zu erstellen raw socket in Python hört sich das für UDP-Pakete nur:
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)
Dieser muss als root ausgeführt werden, und erstellt einen raw socket auf port 1337, das hört sich für UDP-Pakete und gibt Sie aus, wenn Sie empfangen werden; da auch keine Probleme.
Nun machen wir eine kleine client zu testen, ob dies funktioniert:
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')
Konsequent, nur die erste, Dritte und fünfte Botschaft (message 1
, message 3
und message 5
) durch und gedruckt werden, in der server-Ausgabe. Der zweiten, vierten und sechsten Nachrichten nicht zeigen, bis auf der server-Ausgabe, und stattdessen bekommt der Kunde eine Ausnahme:
>>> c.send('message 2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
socket.error: [Errno 111] Connection refused
Laufen diese in Wireshark zeigt, dass es immer eine ICMP-Antwort für "Ziel nicht erreichbar". Ich war in der Lage reproduzieren diese auf 3 verschiedenen Rechnern (alle mit Linux allerdings). Bin ich etwas fehlt? Ist dieses erwartete Verhalten für das UDP-Protokoll konsequent Pakete verwerfen, da die Protokolle, die das benutzen sollen tolerant gegenüber Paketverlust? Auch so, warum sollte Pakete werden gelöscht, wenn gesendet wird auf der lokalen Benutzeroberfläche?
Bindung der server 127.0.0.1
statt 0.0.0.0
hat das gleiche Ergebnis.
- Manchmal geschehen merkwürdige Dinge mit der Meldung stack. Der ethernet-adapter in diesem Fall verwendet die loopback, aber immer noch die Pakete "phsically" gehen noch auf die Karte und dann interpretiert werden, indem der Fahrer wie Sie, um die message queue. nur einige der Forschung, Punkte zu helfen.
- FlavorScape ich bekomme die Fehlermeldung jedes zweite Paket, das scheint viel zu regelmäßig, um ein Netzwerk-Fehler...
- Ja, es passiert jedes der zwei Pakete, was bedeutet, dass, wenn Sie senden
2*n
- Pakete, alle Pakete, die von der form2*i+1
wird nicht durchkommen. Ich glaube nicht, dass diese werden können Paketverlust, da diese alle auf der lokalen Schnittstelle. - Ich vermute, es liegt daran, dass man mit RAW <-> DGRAM oder etwas ähnliches.
- Bestätigt. Wenn Sie eine
socket.SOCK_DGRAM
server-Seite, es funktioniert wie erwartet. - Ja, in der Tat, aber wie die Frage sagt, brauche ich eine raw-socket (um das UDP Paket-header).
- Der Header enthält vier Dinge:
src
, die Sie aus derrecvfrom()
Gegenzugdst
, das ist der port, den du hörst auf, die Länge des Pakets an, die werden nie größer als 2^16, die Sie bekommen können aus dem Paket Lesen aus dem Netzwerk, und die Prüfsumme, die behandelt wird durch den kernel. Was Sie tun müssen? - Ich sollte erwähnt haben, die IP-Paket-header hier auch, aber ich erkannte das zu spät, um den Kommentar Bearbeiten, sorry. Ich brauche das, um zu wissen, was mit dem Paket; es wird weitergeleitet durch
iptables
Du musst angemeldet sein, um einen Kommentar abzugeben.
Löste es in eine Art dumme Art und Weise; lassen Sie mich bitte wissen, ob es einen anderen Weg gibt, und ich die akzeptierte Antwort.
Die Lösung ist einfach zu verwenden, zwei Steckdosen gebunden, die auf dem gleichen port; ein roh, nicht raw:
Das macht das "Ziel nicht erreichbar" ICMP-Pakete gehen Weg und lässt alle Pakete durch gehen in Ordnung. Ich denke, das Betriebssystem will nicht-raw-socket auf den port horcht, für Dinge, die gut gehen, und dann alle raw-sockets lauschen, der auf dem gleichen port erhalten Kopien der Pakete.