¿Cómo se envía y recibe la multidifusión UDP en Python? ¿Hay una biblioteca estándar para hacerlo?Multidifusión en Python
Respuesta
El tráfico de multidifusión no es diferente al UDP normal a excepción de la dirección IP. Eche un vistazo a la norma socket library. Es posible que pueda encontrar algo que se base en el zócalo y que sea más fácil de usar.
multidifusión emisor que transmite a un grupo de multidifusión:
#!/usr/bin/env python
import socket
import struct
def main():
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
sock.sendto('Hello World!', (MCAST_GRP, MCAST_PORT))
if __name__ == '__main__':
main()
multidifusión receptor que lee de un grupo de multidifusión e imprime los datos hexagonales en la consola:
#!/usr/bin/env python
import socket
import binascii
def main():
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
try:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except AttributeError:
pass
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
sock.bind((MCAST_GRP, MCAST_PORT))
host = socket.gethostbyname(socket.gethostname())
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(host))
sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(MCAST_GRP) + socket.inet_aton(host))
while 1:
try:
data, addr = sock.recvfrom(1024)
except socket.error, e:
print 'Expection'
hexdata = binascii.hexlify(data)
print 'Data = %s' % hexdata
if __name__ == '__main__':
main()
Intenté esto, no funcionó. En Wireshark puedo ver la transmisión, pero no veo nada de IGMP y no recibo nada. –
necesita enlazar al puerto/grupo de multidifusión no local en la dirección de multidifusión, 'sock.bind ((MCAST_GRP, MCAST_PORT))' – stefanB
Este ejemplo no funciona para mí, por un motivo oscuro. El uso de socket.gethostbyname (socket.gethostname()) para seleccionar la interfaz no siempre elige la interfaz externa; de hecho, en los sistemas Debian, tiende a seleccionar la dirección de bucle invertido. Debian agrega una entrada de 127.0.1.1 en la tabla de host para el nombre de host. En su lugar, es más efectivo usar socket.INADDR_ANY, que la respuesta de clasificación más alta usa a través de la declaración 'paquete' (que es más correcto que '+'). Además, el uso de IP_MULTICAST_IF no es necesario, ya que la respuesta de mayor rango indica correctamente. –
Esto funciona para mí:
Recibir
import socket
import struct
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', MCAST_PORT)) # use MCAST_GRP instead of '' to listen only
# to MCAST_GRP, not all groups on 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:
print sock.recv(10240)
Enviar
import socket
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
sock.sendto("robot", (MCAST_GRP, MCAST_PORT))
Se basa fuera de los ejemplos de http://wiki.python.org/moin/UdpCommunication que no funcionaba.
Mi sistema es ... Linux 2.6.31-15-generiC# 50-Ubuntu SMP Mar Nov 10 14:54:29 UTC 2009 i686 GNU/Linux Python 2.6.4
Para mac os x necesita usar la opción socket.SO_REUSEPORT como alternativa al socket.SO_REUSEADDR en el ejemplo anterior, para permitir múltiples escuchas en la misma combinación de dirección de puerto multicast. – atikat
Para enviar, también necesitaba "sock.bind ((
para multidifusión udp que necesita vincular al grupo/puerto de multidifusión, no al puerto del grupo local, 'sock.bind ((MCAST_GRP, MCAST_PORT))', su código podría o no funcionar, puede que no funcione cuando tenga múltiples nics – stefanB
Tenga una mirada en py-multicast. El módulo de red puede verificar si una interfaz admite multidifusión (al menos en Linux).
import multicast
from multicast import network
receiver = multicast.MulticastUDPReceiver ("eth0", "238.0.0.1", 1234)
data = receiver.read()
receiver.close()
config = network.ifconfig()
print config['eth0'].addresses
# ['10.0.0.1']
print config['eth0'].multicast
#True - eth0 supports multicast
print config['eth0'].up
#True - eth0 is up
Quizás los problemas para no ver IGMP hayan sido causados por una interfaz que no admite la multidifusión?
un mejor uso:
sock.bind((MCAST_GRP, MCAST_PORT))
en lugar de:
sock.bind(('', MCAST_PORT))
... porque si desea escuchar a varios grupos MCAST en el mismo puerto, obtendrá todos los mensajes en todas oyentes
La respuesta de tolomea funcionó para mí. Pirateé en socketserver.UDPServer también:
class ThreadedMulticastServer(socketserver.ThreadingMixIn, socketserver.UDPServer):
def __init__(self, *args):
super().__init__(*args)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind((MCAST_GRP, MCAST_PORT))
mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
existe un marco que hacer esto desde http://twistedmatrix.com/trac/. Aquí está el ejemplo https://twistedmatrix.com/documents/12.2.0/core/howto/udp.html
Para hacer que el código del cliente (de Tolomea) trabaja en Solaris que necesita para pasar el valor TTL para la opción IP_MULTICAST_TTL
conector como un unsigned char. De lo contrario, obtendrá un error. Esto funcionó para mí en Solaris 10 y 11:
import socket
import struct
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
ttl = struct.pack('B', 2)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
sock.sendto("robot", (MCAST_GRP, MCAST_PORT))
Un buen ejemplo que funciona para mí:
http://svn.python.org/projects/stackless/trunk/Demo/sockets/mcast.py
Para unirse al grupo de multidifusión Python usa la interfaz de socket nativo del sistema operativo.Debido a la portabilidad y estabilidad del entorno de Python, muchas de las opciones de socket se envían directamente a la llamada de setsockopt de socket nativo. El modo de operación de multidifusión, como unirse y abandonar la membresía del grupo, solo se puede realizar al setsockopt
.
programa básico para la recepción de paquetes IP multicast puede verse como:
from socket import *
multicast_port = 55555
multicast_group = "224.1.1.1"
interface_ip = "10.11.1.43"
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("", multicast_port))
mreq = inet_aton(multicast_group) + inet_aton(interface_ip)
s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, str(mreq))
while 1:
print s.recv(1500)
En primer lugar se crea zócalo, se une y activa desencadena grupo de multidifusión unirse mediante la emisión de setsockopt
. Al final, recibe paquetes para siempre.
El envío de marcos IP de multidifusión es sencillo. Si tiene una NIC única en su sistema, el envío de dichos paquetes no difiere del envío habitual de marcos UDP. Todo lo que tiene que hacer es simplemente configurar la dirección IP de destino correcta en el método sendto()
.
Observé que muchos ejemplos de Internet funcionan por accidente de hecho. Incluso en la documentación oficial de Python. Problema para todos ellos están utilizando struct.pack incorrectamente. Tenga en cuenta que el ejemplo típico usa 4sl
como formato y no está alineado con la estructura de interfaz del socket del sistema operativo real.
Intentaré describir lo que sucede debajo del capó cuando ejercito setsockopt llame para el objeto de socket python.
Python reenvía la llamada al método setsockopt a la interfaz del socket C nativo. La documentación de socket de Linux (vea man 7 ip
) presenta dos formas de estructura ip_mreqn
para la opción IP_ADD_MEMBERSHIP. La forma más corta es de 8 bytes de longitud y más de 12 bytes de longitud. El ejemplo anterior genera 8 byte setsockopt
llamada donde puño para bytes define multicast_group
y segundo interface_ip
.
- 1. Multidifusión confiable en Java
- 2. Elegir interfaz de red de multidifusión en Python
- 3. Ninject multidifusión
- 4. Soporte de multidifusión en .Net
- 5. Delegados de multidifusión asincrónica
- 6. Cómo recibir paquetes de multidifusión en Android
- 7. Multidifusión frente a difusión en LAN
- 8. ¿Qué está haciendo la multidifusión en 224.0.0.251?
- 9. Atributos de multidifusión en conjunto. ¿Son malvados?
- 10. Multidifusión, Mensajes, ActiveMQ vs. MSMQ?
- 11. Rendimiento de multidifusión UDP bajo carga
- 12. Seleccionar una dirección IP de multidifusión
- 13. ¿El mejor tutorial para multidifusión de aplicaciones?
- 14. Multidifusión UDP a través de Internet?
- 15. Soporte de multidifusión en Android en el modo Hotspot/Tethering
- 16. recepción de multidifusión en un servidor con múltiples interfaces (Linux)
- 17. ¿Puedo revertir el orden de un evento delegado de multidifusión?
- 18. ¿Es posible la multidifusión con Wi-Fi Direct?
- 19. MSMQ: no se puede recibir de las colas de multidifusión
- 20. ¿Cómo se puede usar chrome.socket para difusión o multidifusión?
- 21. Confusión Mensajería: Pub/Sub vs vs multidifusión Latigador
- 22. multidifusión UDP usando winsock diferencias API entre XP y Vista
- 23. delegado simple (delegado) frente a delegados de multidifusión
- 24. Referencias en Python
- 25. Delegados de multidifusión: varias clases que reciben notificaciones de controles de IU en iOS
- 26. ¿Se ha roto la multidifusión para Android 2.0.1 (actualmente en DROID) o me falta algo?
- 27. Especificar a qué interfaz de red debe conectarse una multidifusión UDP en .NET
- 28. ¿Cómo determino la IP de origen de un paquete de multidifusión en C#?
- 29. UDPClient La recepción de multidifusión falla en la computadora con varias NIC
- 30. Suscripción a múltiples grupos de multidifusión en un socket (Linux, C)
Derecha. ¿Pero qué hay de unirse a un grupo? Me gustaría no rodar mi propia gestión de unión de grupo si es posible. –
El tráfico de multidifusión es muy diferente del tráfico UDP regular (unidifusión): debe unirse al grupo de multidifusión, todos los enrutadores y enrutadores involucrados deben tratar las implicaciones, TTL importa, generalmente no se enruta a través de la WAN. –