我遇到问题,我猜这是代码。
该应用程序用于“ping”某些自定义网络设备,以检查它们是否还活着。它使用特殊的UDP数据包每隔20秒对它们进行一次ping操作并期望响应。如果他们连续3次没有应答,则应用程序会向员工发送警告消息。
应用程序全天候运行并且每天随机播放一次(主要是2-5次),应用程序无法在10分钟的精确时间内收到UDP数据包,之后一切都恢复正常。在那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)
答案 0 :(得分:3)
你没有提到它,所以我必须提醒你,因为你使用select()
该套接字最好是非阻塞的。否则您的recvfrom()
会阻止。在处理得当时不应该真的发生,但很难从短代码片段中辨别出来。
然后你不必检查UDP套接字的可写性 - 它总是可写的。
现在针对真正的问题 - 您说数据包正在进入系统,但您的代码却没有收到它们。这很可能是由于套接字接收缓冲区溢出造成的。 ping目标的数量是否超过过去15年?您正在设置ping响应风暴,并且可能没有足够快地读取这些响应,因此它们堆积在接收缓冲区中并最终被丢弃。
我的投资回报率建议:
SO_RCVBUF
增加到一个较大的值。这将使您的网络堆栈更好地处理数据包突发。EWOULDBLOCK
。这样可以节省大量select()
次电话。recvmmsg(2)
沿线的某些高级Windows API(如果存在这样的话),为每个系统调用出列多个数据包。希望这有帮助。
答案 1 :(得分:0)
UDP无法保证可靠的传输。现在,这可能会在下一个小时和明年发挥作用。然后在两年内它将无法沟通一整个小时。
在某些情况下,可能会阻止数据包的路由路径。当TCP发生这种情况时,将通知发送方丢失,并且发送方可能尝试通过不同的路由路径发送它。由于UDP是“发送 - 忘记”传输协议,因此您可能会在统计上丢失一些数据包。
tl; dr使用TCP。