在Linux和python上,什么使套接字超时?

时间:2017-10-13 03:25:58

标签: python linux sockets

我编写服务器以通过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)

程序的部分输出:

enter image description here

然而,服务器在运行程序时超时。我的问题是,如果网络状况良好,服务器会超时的原因是什么?客户端是否会每5秒收到一次数据导致服务器超时?

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

enter image description here

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

1 个答案:

答案 0 :(得分:0)

"超时"你在这里观察是由于TCP套接字上发生了流量控制。为了有序保证传送,TCP需要有一个接收队列(在client.py)和一个发送队列(在server.py)。如果客户端没有足够快地读取数据,首先接收器队列将填满,然后发送器队列将填满。此时,一旦两个队列都已满,服务器将在调用s.send时阻塞,并且将一直阻塞,直到发送队列中的空间可用为止。

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

netstat -plan | grep ESTABLISHED | grep 8080

E.g。输出看起来像(我手动添加了标题):

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的非零数字,表明它们已经满了,因此发送方在接收方读取之前无法发送。