我编写服务器以通过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窗口大小的阈值,使客户端通知服务器?答案 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的非零数字,表明它们已经满了,因此发送方在接收方读取之前无法发送。