Pergunta

pyzor usa UDP / IP como protocolo de comunicação. Nós recentemente trocou o servidor público para uma nova máquina, e começou a receber relatos de muitos tempos de espera. Eu descobri que eu poderia resolver o problema, se eu mudei o IP que foi consultado a partir eth0:1 para eth0.

Eu posso reproduzir esse problema com um exemplo simples:

Este é o código do 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 é o código do cliente (188.40.77.206 é eth0 188.40.77.236 é o mesmo servidor, mas é 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]

O servidor recebe o pacote "ping" em ambos os casos (e, portanto, envia o pacote "pong" em ambos os casos).

Curiosamente, este não trabalho de alguns lugares (ou seja, eu vou obter uma resposta de ambos os IPs). Por exemplo, ele funciona a partir 188.40.37.137 (mesma rede / datacenter, servidor diferente), mas também de 89.18.189.160 (datacenter diferente). Nesses casos, a resposta recvfrom tem a eth0 IP, em vez do que a que estava conectado.

Isto é apenas uma regra de UDP? É este um problema / limitação com o Python classe UDPServer? É algo que eu estou fazendo de forma incorreta? Existe alguma maneira que eu possa ter este trabalho para além da simples conexão à eth0 IP (ou escutando o específico IP, em vez de 0.0.0.0)?

Foi útil?

Solução

Me deparei com este com um servidor TFTP. Meu servidor tinha dois endereços IP de frente para a mesma rede. Como o UDP é sem conexão, pode haver problemas com endereços IP não sendo definida como esperado nessa situação. A seqüência que eu tinha era:

  1. O cliente envia o pacote inicial para o servidor em um determinado endereço IP
  2. Server lê o endereço de origem do cliente do pacote de entrada, e envia uma resposta.
    1. No entanto, na resposta, "endereço de origem" do servidor é definido de acordo com as tabelas de roteamento, e fica definido para o outros endereço IP.
    2. Não foi possível controlar "fonte" o endereço IP do servidor porque o sistema operacional não nos disse qual endereço IP a solicitação veio em meio.
  3. O cliente recebe uma resposta do "outro" endereço IP, e rejeita-o.

A solução no meu caso era especificamente ligam o servidor TFTP para o endereço IP que eu queria ouvir, em vez de se ligar a todas as interfaces.

Eu encontrei um texto que pode ser relevante em um href="http://man.cx/tftpd%288%29" rel="nofollow noreferrer"> página homem tftpd (TFTP servidor). Aqui 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.

Consulte esta resposta que mostra que em Linux que é possível ler o endereço local para pacotes UDP, e configurá-lo para os pacotes de saída. É possível em C; Eu não tenho certeza sobre Python embora.

Outras dicas

Isto é apenas uma regra de UDP?

Não.

Este é um problema / limitação com o Python UDPServer classe?

duvidoso.

É algo que eu estou fazendo incorretamente?

Seu programa parece correto.

Há um sem número de razões pelas quais o datagrama não está recebendo para o servidor. UDP é sem conexão para que o seu cliente apenas envia o off de ping no éter sem saber se alguém recebe.

Veja se você tem permissão para ligar para esse endereço. Há um pequeno grande programa chamado netcat que funciona muito bem para acesso de baixo nível de rede. Não é sempre disponível em cada sistema, mas é fácil de download e compilação.

nc -l -s 188.40.77.236 -p 24440 -u

Se você executar o seu programa cliente como antes, você deve ver "Ping" impresso em seu terminal. (Você pode digitar Pong e configurá-lo de volta para o seu cliente. É um pouco divertido para brincar.) Se você receber o ping, os problemas de rede não são o problema e algo está errado com o programa do servidor Python ou bibliotecas. Se você não receber o ping, você não pode fazer a conexão. "Contacte o seu administrador de rede para obter assistência."

coisas para verificar se incluem ...

  1. problemas de firewall?
  2. Problemas de configuração com interfaces de rede alias.
  3. problemas de permissão do usuário.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top