Wie senden und empfangen Sie UDP-Multicast in Python? Gibt es dafür eine Standardbibliothek?
85
Das funktioniert bei mir:
Erhalten
import socket
import struct
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
IS_ALL_GROUPS = True
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if IS_ALL_GROUPS:
# on this port, receives ALL multicast groups
sock.bind(('', MCAST_PORT))
else:
# on this port, listen ONLY to MCAST_GRP
sock.bind((MCAST_GRP, MCAST_PORT))
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
# For Python 3, change next line to "print(sock.recv(10240))"
print sock.recv(10240)
Senden
import socket
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
# regarding socket.IP_MULTICAST_TTL
# ---------------------------------
# for all packets sent, after two hops on the network the packet will not
# be re-sent/broadcast (see https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html)
MULTICAST_TTL = 2
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)
# For Python 3, change next line to 'sock.sendto(b"robot", ...' to avoid the
# "bytes-like object is required" msg (https://stackoverflow.com/a/42612820)
sock.sendto("robot", (MCAST_GRP, MCAST_PORT))
Es basiert auf den Beispielen von http://wiki.python.org/moin/UdpCommunication, die nicht funktioniert haben.
Mein System ist ... Linux 2.6.31-15-generic # 50-Ubuntu SMP Di Nov 10 14:54:29 UTC 2009 i686 GNU / Linux Python 2.6.4
sock.bind((MCAST_GRP, MCAST_PORT))
Ihr Code funktioniert möglicherweise nicht und funktioniert möglicherweise nicht. Wenn Sie mehrere Nics habenMulticast-Absender, der an eine Multicast-Gruppe sendet:
Multicast-Empfänger, der aus einer Multicast-Gruppe liest und Hex-Daten an die Konsole druckt:
quelle
sock.bind((MCAST_GRP, MCAST_PORT))
Bessere Verwendung:
anstatt:
Wenn Sie mehrere Multicast-Gruppen am selben Port abhören möchten, erhalten Sie alle Nachrichten von allen Listenern.
quelle
Um einer Multicast-Gruppe beizutreten, verwendet Python die native OS-Socket-Schnittstelle. Aufgrund der Portabilität und Stabilität der Python-Umgebung werden viele Socket-Optionen direkt an den nativen Socket-Sockoptopt-Aufruf weitergeleitet. Multicast-Betriebsmodi wie das Beitreten und Löschen einer Gruppenmitgliedschaft können
setsockopt
nur von ausgeführt werden.Das Basisprogramm zum Empfangen von Multicast-IP-Paketen kann folgendermaßen aussehen:
Erstens wird ein Socket erstellt, gebunden und der Multicast-Gruppenbeitritt durch Ausgabe ausgelöst
setsockopt
. Am Ende empfängt es Pakete für immer.Das Senden von Multicast-IP-Frames ist unkompliziert. Wenn Sie eine einzelne Netzwerkkarte in Ihrem System haben, unterscheidet sich das Senden solcher Pakete nicht vom üblichen Senden von UDP-Frames. Sie müssen sich nur um die richtige Ziel-IP-Adresse kümmern
sendto()
Methode festzulegen.Mir ist aufgefallen, dass viele Beispiele rund um das Internet tatsächlich zufällig funktionieren. Auch auf offizielle Python-Dokumentation. Das Problem für alle ist, dass struct.pack falsch verwendet wird. Bitte beachten Sie, dass typische Beispiele verwendet werden
4sl
als Format verwendet wird und nicht mit der tatsächlichen Struktur der OS-Socket-Schnittstelle übereinstimmt.Ich werde versuchen zu beschreiben, was unter der Haube passiert, wenn der Aufruf von setsockopt für das Python-Socket-Objekt ausgeführt wird.
Python leitet den Methodenaufruf setsockopt an die native C-Socket-Schnittstelle weiter. In der Linux-Socket-Dokumentation (siehe
man 7 ip
) werden zweiip_mreqn
Strukturformen für die Option IP_ADD_MEMBERSHIP eingeführt. Die kürzeste Form ist 8 Byte lang und die längere 12 Byte. Das obige Beispiel generiert einen 8-Byte-setsockopt
Aufruf, bei dem die ersten vier Bytesmulticast_group
und die zweiten vier Bytes definiert werdeninterface_ip
.quelle
Schauen Sie sich py-multicast an . Das Netzwerkmodul kann prüfen, ob eine Schnittstelle Multicast unterstützt (zumindest unter Linux).
Vielleicht wurden Probleme mit dem Nicht-Sehen von IGMP durch eine Schnittstelle verursacht, die Multicast nicht unterstützt?
quelle
Nur eine weitere Antwort, um einige subtile Punkte im Code der anderen Antworten zu erklären:
socket.INADDR_ANY
- (Bearbeitet) Im Kontext vonIP_ADD_MEMBERSHIP
bindet dies den Socket nicht wirklich an alle Schnittstellen, sondern wählt einfach die Standardschnittstelle, an der Multicast aktiv ist (gemäß Routing-Tabelle).Siehe Was bedeutet es, einen Multicast-Socket (UDP) zu binden?Weitere Informationen zur Funktionsweise von Multicast
Multicast-Empfänger:
Beispielnutzung: (Führen Sie die folgenden Schritte in zwei Konsolen aus und wählen Sie Ihr eigenes --iface aus (muss mit der Schnittstelle identisch sein, die die Multicast-Daten empfängt))
python3 multicast_recv.py --iface='192.168.56.102' --join-mcast-groups '224.1.1.1' '224.1.1.2' '224.1.1.3' --bind-group '224.1.1.2'
python3 multicast_recv.py --iface='192.168.56.102' --join-mcast-groups '224.1.1.4'
Multicast-Absender:
Beispielverwendung: # Angenommen, der Empfänger bindet an die unten angegebene Multicast-Gruppenadresse und einige Programmanfragen, um dieser Gruppe beizutreten. Um den Fall zu vereinfachen, nehmen Sie an, dass sich Empfänger und Absender im selben Subnetz befinden
python3 multicast_send.py --mcast-group '224.1.1.2'
python3 multicast_send.py --mcast-group '224.1.1.4'
quelle
Damit der Clientcode (von tolomea) unter Solaris funktioniert, müssen Sie den ttl-Wert für die
IP_MULTICAST_TTL
Socket-Option als vorzeichenloses Zeichen übergeben. Andernfalls erhalten Sie eine Fehlermeldung. Dies funktionierte für mich unter Solaris 10 und 11:quelle
Tolomeas Antwort hat bei mir funktioniert. Ich habe es auch in socketserver.UDPServer gehackt :
quelle