Servidor UDP de Python simple: problemas para recibir paquetes de clientes que no sean localhost

Entonces, el código muy simple que estoy tratando de usar está aquí: http://wiki.python.org/moin/UdpCommunication

(También aquí): Enviando:

import socket UDP_IP = "127.0.0.1" UDP_PORT = 5005 MESSAGE = "Hello, World!" print "UDP target IP:", UDP_IP print "UDP target port:", UDP_PORT print "message:", MESSAGE sock = socket.socket(socket.AF_INET, # Internet socket.SOCK_DGRAM) # UDP sock.sendto(MESSAGE, (UDP_IP, UDP_PORT)) 

Recepción:

 import socket UDP_IP = "127.0.0.1" UDP_PORT = 5005 sock = socket.socket(socket.AF_INET, # Internet socket.SOCK_DGRAM) # UDP sock.bind((UDP_IP, UDP_PORT)) while True: data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes print "received message:", data 

El código funciona bien cuando ejecuto ambas aplicaciones en mi computadora. Pongo el código de envío en mi laptop con:

 UDP_IP="IP address for my computer" 

Todo lo demás es lo mismo. Sin embargo, no pasa nada. ¿Qué estoy haciendo incorrectamente? Usé wireshark y determiné que el paquete se está enviando y recibiendo; sin embargo, el progtwig python no está recibiendo el paquete. Estoy muy confundido.

Cualquier ayuda es muy apreciada. Gracias por adelantado.

Intente enlazar a todas las interfaces locales en el lado receptor:

 sock.bind(("", UDP_PORT)) # could also use "0.0.0.0" 

Tenga en cuenta que el comportamiento de los sistemas operativos no es totalmente lógico (ni coherente) en términos de enlace cuando se reciben paquetes UDP, especialmente para el tráfico de multidifusión. Este es el comportamiento que obtienes:

Linux: el enlace a una IP específica filtrará los paquetes UDP entrantes y solo los que estén dirigidos a esta IP específica pasarán a través del filtro. Esto significa, por ejemplo, que los paquetes UDP de multidifusión recibidos por una interfaz con IP 192.168.1.100 no se recibirán cuando se vinculen a IP 192.168.1.100. En Linux, el enlace normal no se enlaza a una interfaz. Use setsockopt (SO_BINDTODEVICE) para esto. La vinculación a 0.0.0.0 (o “” en Python) siempre recibirá todos los paquetes UDP recibidos por la máquina en todas las interfaces, independientemente de la IP de destino, por lo que esta suele ser la opción más útil en Linux.

Windows: el enlace a una IP específica se vinculará a la interfaz que pertenece a esta IP, al igual que lo hace setsockopt (SO_BINDTODEVICE) en Linux. Los paquetes UDP entrantes no se filtran por esta IP, por lo que se puede recibir tráfico de multidifusión incluso cuando se vincula a una IP concreta. (Esta es probablemente la primera vez que el comportamiento de Windows me parece más consistente que el comportamiento de Linux).

Python no abstrae estas diferencias específicas de SO para sockets (como lo hace en otras áreas). Siempre y cuando no tenga una razón explícita para no hacerlo, le sugiero que siempre se vincule a 0.0.0.0.

finalmente resolví mi problema y era bastante complejo y altamente localizado,

Me pasó un problema muy similar. Me doy cuenta de que ya resolviste este problema, sin embargo, pensé que sería bueno compartir cómo resolví el problema por mí.

El problema que encontré fue con mi configuración de firewall. Encontré que los paquetes estaban siendo bloqueados por el Firewall de Windows.

Yo también había usado Wireshark que mostraba que los paquetes se estaban enviando y recibiendo. Es importante tener en cuenta que Wireshark toma paquetes a un nivel mucho más bajo que una aplicación Python.

Al ejecutar mi código localmente con un agente de escucha en un puerto y un cliente en otro puerto en la misma PC, el firewall no estaba bloqueando los paquetes. Cuando pasé a la interfaz con una máquina externa, las reglas del firewall entraron en juego bloqueando los paquetes entrantes.

Cambiar la política de firewall solucionó este problema. Existen muchas formas y riesgos de seguridad inherentes al cambio del firewall para que esto funcione, por lo que dejaré esa parte a los profesionales de TI. 🙂

Asegúrese de que el puerto del servidor esté abierto al intentar ejecutar la llamada de recvfrom . Si el puerto de destino desde el cual la lectura del socket estaba fuera de servicio, obtenemos este error.

Recibí el mismo error y lo solucioné leyendo este enlace: http://www.linuxsa.org.au/mailing-list/2001-04/668.html

Entonces, si quiero enviar un mensaje Y recibir una respuesta, ¿cómo se verá el código? ¿Me gusta esto?

 import socket UDP_IP = "127.0.0.1" UDP_PORT = 5005 MESSAGE = "Hello, World!" sock = socket.socket(socket.AF_INET, # Internet socket.SOCK_DGRAM) # UDP sock.sendto(MESSAGE, (UDP_IP, UDP_PORT)) sock.bind((UDP_IP, UDP_PORT)) while True: data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes print "received message:", data