Python UDP套接字半随机失败接收
我有一些问题,我猜它是代码。Python UDP套接字半随机失败接收
该应用程序用于'ping'一些定制的网络设备来检查它们是否还活着。它每隔20秒用一个特殊的UDP数据包对它们进行处理并期望得到响应。如果他们连续三次ping不回答,应用程序会向员工发送警告消息。
应用程序每天24小时运行一次(主要是2-5次)应用程序无法接收UDP数据包,精确时间为10分钟,然后一切恢复正常。在这10分钟内,只有1个设备似乎在回复,其他设备似乎已经死机。我已经能够从日志中推断出来。
我已经使用wireshark来嗅探数据包,并且我已经验证过ping数据包都出去了,所以网络部分似乎工作正常,一直到操作系统。电脑运行WinXPPro,有些没有配置防火墙。我在不同的计算机,不同的Windows安装和不同的网络上都有这个问题。
我真的不知道这里可能是什么问题。
我附上了执行所有网络的代码的相关部分。这是在与应用程序其余部分分离的线程中运行的。
我可以提前感谢您提供的任何洞察。
def monitor(self):
checkTimer = time()
while self.running:
read, write, error = select.select([self.commSocket],[self.commSocket],[],0)
if self.commSocket in read:
try:
data, addr = self.commSocket.recvfrom(1024)
self.processInput(data, addr)
except:
pass
if time() - checkTimer > 20: # every 20 seconds
checkTimer = time()
if self.commSocket in write:
for rtc in self.rtcList:
try:
addr = (rtc, 7) # port 7 is the echo port
self.commSocket.sendto('ping',addr)
if not self.rtcCheckins[rtc][0]: # if last check was a failure
self.rtcCheckins[rtc][1] += 1 # incr failure count
self.rtcCheckins[rtc][0] = False # setting last check to failure
except:
pass
for rtc in self.rtcList:
if self.rtcCheckins[rtc][1] > 2: # didn't answer for a whole minute
self.rtcCheckins[rtc][1] = 0
self.sendError(rtc)
你没有提到它,所以我不得不提醒你,因为你使用的是select()
这个socket最好是非阻塞的。否则你的recvfrom()
可以阻止。处理得当时应该不会发生,但很难从简短的代码片段中看出来。
然后,您不必检查UDP套接字的可写性 - 它始终是可写的。
现在真正的问题 - 你说的数据包进入系统,但你的代码没有收到它们。这很可能是由于套接字接收缓冲区的溢出。 ping命令的数量是否比过去15年增加了?您正在设置自己的ping响应风暴,并且可能没有足够快地读取这些响应,所以它们堆积在接收缓冲区中并最终被丢弃。
我的投资回报率的顺序建议:
- 摊开ping请求,不要为自己设定了一个DDOS。每个迭代查询一个系统,并保持每个目标的最后检查时间。这将允许你将数据包的数量统统输出。
- 将
SO_RCVBUF
增加到一个很大的值。这将使您的网络堆栈更好地处理数据包突发。 - 在一个循环中读取数据包,即一旦您的UDP套接字可读(假设它是非阻塞的),读取,直到获得
EWOULDBLOCK
。这将为您节省大量的select()
电话。 - 看看您是否可以使用Linux
recvmmsg(2)
的某些高级Windows API(如果存在这种情况)为每个系统调用排队多个数据包。
希望这会有所帮助。
其实套接字处于阻塞模式,但我已经有一些记录,证实我从来没有遇到过这个问题。至于可能的DDOS,这个问题发生在具有4个设备和20个系统(这是我们拥有的最大部署系统)的系统中,所以我不会相信它是DOS的问题。我会将您的建议带入代码并返回结果。谢谢! – flowInTheDark 2012-07-19 07:01:13
使缓冲区变大没有帮助,奇怪的是。最后有什么帮助的是你的建议是在每次读取它时读取套接字,直到EWOULDBLOCK可读。现在它的工作方式应该如此。谢谢! – flowInTheDark 2012-08-07 13:06:43
UDP不保证可靠的传输。现在可以工作了,接下来的一个小时和第二年。然后在两年内它将无法沟通整整一个小时。
在某些情况下,数据包的路由路径可能会被阻塞。当TCP发生这种情况时,发件人会被告知丢失,并且发件人可能会尝试通过不同的路径路径发送它。由于UDP是“发送与忘记”传输协议,因此您可能会丢失一些统计数据包。
tl; dr使用TCP。
请注意文本中提到我的wireshark嗅探并确认数据包实际进入系统的部分。 – flowInTheDark 2012-07-18 08:01:22
不要忘记,UDP不能保证可靠的传输:http://en.wikipedia.org/wiki/User_Datagram_Protocol – 2012-07-18 07:50:41
我知道这一点,但这里的遗留系统非常可靠地使用UDP 15年左右而系统的其他部分没有这样的问题。 – flowInTheDark 2012-07-18 07:57:06