Python套接字recv需要很长时间才能传递数据包
我有一个Python3程序,它向主机发送短命令并返回短响应(都是20字节)。它没有做任何复杂的事情 插座是这样打开的:Python套接字recv需要很长时间才能传递数据包,python,linux,sockets,networking,delay,Python,Linux,Sockets,Networking,Delay,我有一个Python3程序,它向主机发送短命令并返回短响应(都是20字节)。它没有做任何复杂的事情 插座是这样打开的: self.conn = socket.create_connection( ( self.host, self.port ) ) self.conn.settimeout( POLL_TIME ) while( True ): buf = self.conn.recv( 256 ) # append buffer to bigger buffer,
self.conn = socket.create_connection( ( self.host, self.port ) )
self.conn.settimeout( POLL_TIME )
while( True ):
buf = self.conn.recv( 256 )
# append buffer to bigger buffer, parse packet once we've got enough bytes
使用方法如下:
self.conn = socket.create_connection( ( self.host, self.port ) )
self.conn.settimeout( POLL_TIME )
while( True ):
buf = self.conn.recv( 256 )
# append buffer to bigger buffer, parse packet once we've got enough bytes
在我的程序运行了一段时间(通常是几个小时)之后,有时它会进入一种奇怪的模式——如果我使用tcpdump,我可以看到一个响应包到达本地机器,但是recv直到30秒(Windows)到1米(Linux)之后才给我这个包。时间是随机的+/-大约10秒。我想知道包是否被延迟到下一个包到达,但这似乎不是真的
同时,同一程序还在另一个线程上使用相同的代码操作第二个套接字连接,该线程将继续正常工作
这种情况并非总是发生,但在一个月内发生了好几次。有时,在它之前会有几秒钟的数据包,需要越来越长的时间才能到达,但大多数情况下,它只是从OK(正常)到完全中断。在我重新启动服务器之前,它大部分时间都会坏几个小时,但昨晚我注意到它正在恢复并恢复正常运行,所以它不是不可恢复的
CPU使用率几乎为零,并且在同一台机器上没有其他任何东西在运行
最奇怪的是,这种情况发生在Windows的Linux子系统(两台不同的笔记本电脑)和Linux(运行AmazonLinux的AWS小实例)上
我看了一下使用GDB实现socket.recv()的CPython。查看源代码,它似乎将对socket.recv()的调用直接传递到底层recv()。但是,虽然外部函数sock_recv()(实现socket.recv())经常被调用,但它只在实际有数据要从套接字读取时才调用recv(),使用socket_call()函数调用poll()/select(),查看是否有数据等待。对recv()的调用直接发生在应用程序收到数据包之前,因此延迟在该点之前,而不是recv()和我的代码之间
关于如何解决这个问题有什么想法吗
(Linux和Windows机器都更新为最新的everything,Python是Python 3.6.2)
[编辑]这个问题变得更加奇怪。我受够了,写了一个方法来检测这个问题(在一行中查找十个延迟到达的数据包,其往返时间几乎相同),断开连接并重新连接(通过关闭以前的连接并创建一个新的套接字对象)。。。但它不起作用。即使有一个新的套接字对象,延迟的数据包也会保持完全相同的延迟量。所以我改变了方法,完全杀死运行该代码的线程并重新启动它,原因是可能存在一些线程本地状态。那仍然不起作用。我唯一剩下的办法就是杀掉整个程序,让看门狗重新启动它
[edit2]杀掉整个程序并用外部看门狗重新启动它起作用。这是一个糟糕的解决方案,但至少是一个解决方案。原因在于:Axalix:套接字已经设置了超时(100ms)。在几次socket.recv()调用均未返回任何结果后,数据包被延迟了整整一分钟才送达。您能否生成一个?@AndyWalker,但只有一个超时时间是不够的。我在第一条评论中发布的链接不是关于超时的。你能将以太网线从你的计算机上拔下30秒,然后重新插上吗?(我的怀疑是,您可能看到TCP通过将重发速率和窗口大小拨回极小值来响应临时网络中断)