Reciba los datagtwigs UDP de multidifusión con python en Linux

Tengo un dispositivo de hardware que envía datos de multidifusión en mi red. He escrito un script de python que recibe los datos y los imprime. Sin embargo, he descubierto que solo funciona en mi PC con Windows XP y no en mi PC con Ubuntu Linux 10.04. Bajo Linux, nada se recibe. Simplemente da la vuelta al bucle while y nunca se recibe ningún dato. Mi código se publica a continuación. ¿Puedes ver alguna razón por la que esto no funcionará en Linux? Gracias, Rab.

# Multicast client # Adapted from: http://chaos.weblogs.us/archives/164 # on 05/03/2013 import socket ANY = "0.0.0.0" MCAST_ADDR = "224.0.33.154" MCAST_PORT = 31800 # Create a UDP socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # Allow multiple sockets to use the same PORT number sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # Bind to the port that we know will receive multicast data sock.bind((ANY,MCAST_PORT)) # Tell the kernel that we are a multicast socket sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) # Tell the kernel that we want to add ourselves to a multicast group # The address for the multicast group is the third param status = sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY)); # setblocking(0) is equiv to settimeout(0.0) which means we poll the socket. # But this will raise an error if recv() or send() can't immediately find or send data. sock.setblocking(0) while 1: try: data, addr = sock.recvfrom(1024) except socket.error as e: pass else: print "From: ", addr print "Data: ", data 

Aquí hay algunos resultados de muestra de mi PC con Windows:

 From: ('0.0.0.0', 31801) Data: EDCP 

Tenga en cuenta que el dispositivo de hardware remoto no tiene una dirección IP y está utilizando la dirección 0.0.0.0

EDITAR: Ahora he encontrado que esto tampoco funciona en mi computadora portátil con Windows. Por lo tanto, no parece que sea específico para el sistema operativo. Además, he intentado ejecutar otro script para enviar datos de multidifusión a la misma dirección y puerto de multidifusión. Puedo enviar desde una PC y todas las demás pueden recibir correctamente usando mi script de recepción. Pero solo mi PC con Windows puede recibir los datos del dispositivo de hardware en cuestión. Me pregunto si es algo que ver con los adaptadores de Ethernet o su configuración. ¿Podría tener algo que ver con el hecho de que el dispositivo de hardware tiene una dirección IP 0.0.0.0 y que estos adaptadores de Ethernet y / o el script de mi receptor deben recibir los mensajes con esta dirección? La ejecución de Wireshark en las PC con Linux ve los datos del dispositivo de hardware.

Intente enlazar a la dirección de grupo de multidifusión en su lugar:

 sock.bind((MCAST_ADDR,MCAST_PORT)) 

Además, no es necesario configurar TTL de multidifusión en el receptor, eso es para los remitentes, y también es opcional.

Luché contra este mismo problema durante dos días. Wireshark vio los paquetes, pero mi código no lo hizo. Ninguna de las respuestas supuestamente “definitivas” de varias fonts funcionó para mí. La clave provino de https://serverfault.com/questions/163244/linux-kernel-not-passing-through-multicast-udp-packets .

Ejecutar “ip maddr” mostró que el código similar al suyo no estaba agregando la dirección de multidifusión a ninguna interfaz. Lo forcé a ser agregado con smcroute (vea el enlace de arriba). Todavía no hay alegría. Los paquetes tienen una IP de origen de 172.22 … Mi interfaz es 172.17 … Agregué una dirección 172.22 a esa NIC. ¡Bingo! Ahora mi código recibió los paquetes.

Ahora, ¿cómo hacer que el progtwig funcione sin smcroute? Comenté las llamadas setsockopt (). Todavía trabajaba. Desenlace la dirección de multidifusión con smcroute – falló. Sin comentar las llamadas a setsockopt () y reemplazó “ANY” con mi dirección 172.22. ¡Éxito!

Resumen:

  1. Asegúrese de tener una IP en el mismo segmento de red que los paquetes entrantes.
  2. Use esa dirección en la llamada IP_ADD_MEMBERSHIP en lugar de INADDR_ANY.

Es posible que no necesite hacer 2) si solo tiene una NIC. Tengo tres y debo hacerlo.

En caso de que sea pertinente, estoy usando Ubuntu 12.04. No tuve que cambiar ninguna de las configuraciones predeterminadas de /etc/sysctl.conf como otros han descrito. Los probé. No ayudaron, así que los restablecí a los valores predeterminados de instalación.