皮佐尔 使用UDP/IP作为通信协议。我们最近将公共服务器切换到了一台新机器,并开始收到许多超时的报告。我发现如果我更改查询的IP就可以解决问题 eth0:1eth0.

我可以用一个简单的例子重现这个问题:

这是服务器代码:

#! /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()

这是客户端代码(188.40.77.206eth0. 188.40.77.236 是同一台服务器,但是 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]

服务器在这两种情况下都会收到“ping”数据包(因此在这两种情况下都会发送“pong”数据包)。

奇怪的是,这个 在某些地方工作(即我会收到两个 IP 的响应)。例如,它的工作原理是 188.40.37.137 (相同的网络/数据中心,不同的服务器),但也来自 89.18.189.160 (不同的数据中心)。在这些情况下, recvfrom 响应确实有 eth0 IP,而不是连接到的 IP。

这只是UDP的规则吗?这是一个问题/限制吗 Python UDPServer 班级?是我做错了什么吗?除了简单地连接到 eth0 IP(或侦听特定 IP,而不是 0.0.0.0)?

有帮助吗?

解决方案

我在 TFTP 服务器上遇到过这个问题。我的服务器有两个面向同一网络的 IP 地址。由于 UDP 是无连接的,因此在这种情况下可能会出现 IP 地址未按预期设置的问题。我的顺序是:

  1. 客户端将初始数据包发送到特定 IP 地址的服务器
  2. 服务器从传入数据包中读取客户端的源地址,并发送响应。
    1. 然而,在响应中,服务器的“源地址”是根据路由表设置的,并且它被设置为 其他 IP地址。
    2. 无法控制服务器的“源”IP 地址,因为操作系统没有告诉我们请求是通过哪个 IP 地址传入的。
  3. 客户端收到来自“其他”IP 地址的响应,并拒绝它。

我的解决方案是将 TFTP 服务器专门绑定到我想要监听的 IP 地址,而不是绑定到所有接口。

我发现了一些可能与以下内容相关的文字 Linux 手册页 tftpd (TFTP 服务器)。这里是:

 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.

这个答案 这表明在 Linux 上 可以读取传入 UDP 数据包的本地地址,并将其设置为传出数据包。在C语言中这是可能的;不过我不确定Python。

其他提示

这只是UDP的规则吗?

不。

这是Python udpserver类的问题/限制吗?

疑。

是我做错了什么吗?

你的程序看起来是正确的。

数据报无法到达服务器的原因有很多。UDP 是无连接的,因此您的客户端只需将 ping 发送到以太网中,而不知道是否有人收到它。

查看是否允许您绑定到该地址。有一个名为 netcat 的很棒的小程序,非常适合低级别的网络访问。它并不总是在每个系统上都可用,但它很容易下载和编译。

nc -l -s 188.40.77.236 -p 24440 -u

如果您像以前一样运行客户端程序,您应该会在终端上看到“Ping”。(您可以输入 Pong 并将其设置回您的客户端。玩起来很有趣。)如果您收到 ping 信号,则网络问题不是问题,而是 Python 服务器程序或库出现问题。如果没有收到 ping 信号,则无法建立连接。“请联系您的网络管理员寻求帮助。”

要检查的事项包括...

  1. 防火墙问题?
  2. 别名网络接口的配置问题。
  3. 用户权限问题。
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top