【问题标题】:On Linux and by python,what makes a socket timeout?在 Linux 和 python 上,是什么导致套接字超时?
【发布时间】:2017-10-13 03:25:58
【问题描述】:

我编写了一个服务器通过python向客户端发送数据,代码如下:

server.py

import socket,time
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  #just for test
sock.bind(("10.144.74.182",8080))
sock.listen(10)
s,info=sock.accept()
s.settimeout(60)
while 1:
  try:
     t=time.time()
     s.send("a"*4096)
     print time.time()-t
  except:
     print time.time()-t
     break

client.py

import socket,time
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(("10.144.74.182",8080))
while 1:
   time.sleep(5)
   a=sock.recv(4096)

程序的部分输出:

但是,运行程序时服务器超时。我的问题是,如果网络良好,服务器为什么会超时?客户端每 5 秒接收一次数据会不会导致服务器超时?

通过tcpdump,我找到了原因,当客户端的tcp recv窗口大小再次大于零时,客户端不会立即通知服务器,它会通知服务器,直到它的recv窗口大小大于某个值,可以从下面的图片中看出:

从图中我们可以看到客户端在窗口大小为26368时通知服务器。有没有人知道客户端通知服务器的recv窗口大小的阈值?

【问题讨论】:

  • 如果你想跟踪客户端,不要使用timeout。另一点是timeout 仅适用于单个数据包(不是整个通信)。
  • 你说的“不是完整的交流”是什么意思?
  • Timeout 通常定义连接是否存在或者系统的最长等待时间。此超时仅适用于单个数据包。它不用于文件或流控制,因为网络的状态和资源的可访问性不稳定。出于这个原因,在套接字应用程序中使用了额外的数据块和标志。如果要建立与高速和 amplen 的连接,超时功能将不起作用(忽略)。如果要建立关键数据连接,则以特定时间间隔(

标签: python linux sockets


【解决方案1】:

您在此处观察到的“超时”是由于 TCP 套接字上发生的流量控制。为了有序保证交付,TCP 需要有一个接收者队列(在 client.py 中)和一个发送者队列(在 server.py 中)。如果客户端读取数据的速度不够快,首先接收者队列会填满,然后发送者队列会填满。此时,一旦两个队列都满了,服务器将在调用s.send 时阻塞,并一直阻塞直到发送队列中有可用空间。

如果在 linux 上,您可以使用 netstat 命令查看套接字队列。

netstat -plan | grep ESTABLISHED | grep 8080

例如输出看起来像(我手动添加了标题):

Proto  Recv-Q   Send-Q  Local Address     Foreign Address  State       PID/Program name
tcp    795855        0  127.0.0.1:33652   127.0.0.1:8080   ESTABLISHED 1529/python     
tcp        0   2743089  127.0.0.1:8080    127.0.0.1:33652  ESTABLISHED 1525/python  

...在这里,可以看到 Recv-Q 和 Send-Q 的非零数字,表明它们已经满了,所以发送方在接收方读取之前无法发送。

【讨论】:

    猜你喜欢
    • 2011-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多