Python套接字recv需要很长时间才能传送数据包

时间:2017-12-29 16:31:38

标签: python linux sockets networking delay

我有一个Python 3程序,它向主机发送短命令并返回短响应(均为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, parse packet once we've got enough bytes

我的程序运行一段时间后(通常是几小时),有时会进入一个奇怪的模式 - 如果我使用tcpdump,我可以看到一个响应数据包到达本地机器,但是recv没有在30秒(Windows)到1m(Linux)之后给我这个数据包。时间是随机的+/-大约十秒钟。我想知道数据包是否被延迟直到下一个数据包到达,但这似乎不是真的。

与此同时,同一个程序也在不同的线程上使用相同的代码运行第二个套接字连接,这继续正常工作。

这并不是一直发生的,但它在一个月内发生了好几次。有时它会在几秒钟之后花费更长时间才能到达,但大部分时间它只是直接从OK到完全破坏。大部分时间它都会在重新启动服务器之前保持数小时不间断,但昨晚我发现它恢复正常并恢复正常运行,因此无法恢复。

CPU使用率几乎为零,并且在同一台机器上没有其他任何东西在运行。

最奇怪的是,这种情况发生在适用于Windows的Linux子系统(两台不同的笔记本电脑)和Linux(运行亚马逊Linux的AWS微型实例)上。

我使用GDB查看了socket.recv()的CPython实现。查看源代码,看起来它将对socket.recv()的调用直接传递给底层的recv()。但是,当外部函数sock_recv()(实现socket.recv())被频繁调用时,它只调用recv(),当实际要从套接字读取数据时,使用socket_call()函数调用poll()/ select()查看是否有任何数据等待。对应用recv()的调用直接发生在应用程序收到数据包之前,因此延迟在该点之前,而不是在recv()和我的代码之间。

有关如何解决此问题的任何想法?

(Linux和Windows机器都更新到最新的一切,Python是Python 3.6.2)

[编辑]这个问题更加怪异。我厌倦了并且编写了一种方法来检测问题(查找连续几天往返时间数相近的十个迟到的数据包),删除连接并重新连接(通过关闭先前的连接并创建一个新的套接字对象)。 .. 并且它没有工作。即使使用新的套接字对象,延迟的数据包仍会延迟相同的数量。所以我改变了方法来完全杀死运行该代码的线程并重新启动它,推断可能存在一些线程局部状态。 那仍然无法正常工作。我离开的唯一办法是杀死整个程序,并有一个看门狗重启它......

[edit2]杀死整个程序并使用外部监视程序重新启动它。这是一个可怕的解决方案,但至少它是一个解决方案。

0 个答案:

没有答案