Pregunta

Pyzor utiliza UDP / IP como protocolo de comunicación. Recientemente hemos cambiado el servidor público a una nueva máquina, y empezamos a recibir informes de muchos tiempos de espera. Yo descubrí que podía solucionar el problema si cambiaba la IP que se ha consultado a partir de eth0:1 eth0.

Puedo reproducir este problema con un simple ejemplo:

Este es el código del servidor:

#! /usr/bin/env python

import SocketServer

class RequestHandler(SocketServer.DatagramRequestHandler):
    def handle(self):
        print self.packet
        self.wfile.write("Pong")

s = SocketServer.UDPServer(("0.0.0.0", 24440), RequestHandler)
s.serve_forever()

Este es el código de cliente (188.40.77.206 es eth0 188.40.77.236 es el mismo servidor, pero es eth0:1.):

>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.sendto('ping', 0, ("188.40.77.206", 24440))
4
>>> s.recvfrom(1024)
('Pong', ('188.40.77.206', 24440))
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.sendto('ping', 0, ("188.40.77.236", 24440))
4
>>> s.recvfrom(1024)
[never gets anything]

El servidor recibe el paquete "ping" en ambos casos (y por lo tanto envía el paquete "pong" en ambos casos).

Curiosamente, este hace el trabajo de algunos lugares (es decir, voy a conseguir una respuesta de ambos IPs). Por ejemplo, se trabaja a partir de 188.40.37.137 (misma red / centro de datos, servidor diferente), pero también de 89.18.189.160 (centro de datos diferente). En esos casos, la respuesta recvfrom tiene la IP eth0, en lugar de la que estaba conectado a.

Se trata sólo de una regla de la UDP? ¿Es un problema / limitación con el href="http://python.org" rel="nofollow noreferrer"> Python clase UDPServer eth0 (o escuchando en el IP específica en lugar de 0.0.0.0)?

¿Fue útil?

Solución

Me encontré con este con un servidor TFTP. Mi servidor tenía dos direcciones IP frente a la misma red. Debido a que UDP es sin conexión, no puede haber problemas con las direcciones IP no se fijan como se esperaba en esa situación. La secuencia que tenía era:

  1. Cliente envía el paquete inicial con el servidor en un determinado dirección IP
  2. Server lee la dirección de origen del cliente desde el paquete entrante, y envía una respuesta.
    1. Sin embargo, en la respuesta, "dirección de origen" del servidor se establece de acuerdo a las tablas de enrutamiento, y se establece en el otro dirección IP.
    2. No fue posible controlar la dirección IP "fuente" del servidor, ya que el sistema operativo no nos qué dirección IP petición contó entró por.
  3. El cliente obtiene una respuesta de la "otra" dirección IP, y lo rechaza.

La solución en mi caso era para unirse específicamente al servidor TFTP a la dirección IP que quería escuchar, en lugar de unirse a todas las interfaces.

He encontrado un texto que pueda ser relevante en una página del manual Linux para tftpd (servidor TFTP). Aquí está:

 Unfortunately, on multi-homed systems, it is impossible for tftpd to
 determine the address on which a packet was received. As a result, tftpd
 uses two different mechanisms to guess the best source address to use for
 replies. If the socket that inetd(8) passed to tftpd is bound to a par‐
 ticular address, tftpd uses that address for replies. Otherwise, tftpd
 uses ‘‘UDP connect’’ to let the kernel choose the reply address based on
 the destination of the replies and the routing tables. This means that
 most setups will work transparently, while in cases where the reply
 address must be fixed, the virtual hosting feature of inetd(8) can be
 used to ensure that replies go out from the correct address.  These con‐
 siderations are important, because most tftp clients will reject reply
 packets that appear to come from an unexpected address.

este respuesta que muestra que en Linux que es posible leer la dirección local para los paquetes UDP entrantes, y configurarlo para los paquetes salientes. Es posible en C; No estoy seguro acerca de Python sin embargo.

Otros consejos

  

Se trata sólo de una regla de la UDP?

No.

  

¿Es un problema / limitación con el   Python UDPServer clase?

dudoso.

  

¿Es algo que estoy haciendo mal?

Su programa es correcta.

Hay un buen número de razones por las que el datagrama no está recibiendo al servidor. UDP es sin conexión para que su cliente simplemente envía el ping fuera en el éter sin saber si alguien lo recibe.

A ver si se le permite unirse a esa dirección. Hay un gran pequeño programa llamado netcat que funciona muy bien para el acceso a bajo nivel de red. No siempre está disponible en todos los sistemas, pero es fácil de descargar y compilar.

nc -l -s 188.40.77.236 -p 24440 -u

Si ejecuta su programa cliente al igual que antes, debería ver "ping" impreso en su terminal. (Puede escribir Pong y configurarlo de nuevo a su cliente. Es un poco divertido para jugar.) Si se obtiene el ping, los problemas de red no son el problema y algo está mal con el programa de servidor Python o bibliotecas. Si usted no recibe el ping, no se puede realizar la conexión. "Póngase en contacto con su administrador de red para obtener ayuda."

Lo que debe verificar incluiría ...

  1. Firewall problemas?
  2. Problemas de configuración con las interfaces de red con alias.
  3. problemas con los permisos del usuario.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top