[英]Python TCP Server blocks forever in send to client if client is stopped (SIGSTOP)
我在python中有一个非常简单的tcp服务器,其代码如下:
#!/usr/bin/env python
import socket
sock = socket.socket()
sock.bind(('',3912))
sock.listen(100)
num_cons = 10
cons = []
for i in range(num_cons):
con, addr = sock.accept()
cons.append(con)
while True:
for con in cons:
msg = "a"* 1000
num_sent = con.send(msg.encode())
print("sent: {} bytes of msg:{}".format(str(num_sent), msg))
相应的客户端代码是
#!/usr/bin/env python
import socket
sock = socket.socket()
sock.connect(('',3912)) # in reality here I use the IP of the host where
# I run the server since I launch the clients on a different host
while True:
data = sock.recv(1000)
print("received data: {} ".format(str(data)))
现在,如果我用以下命令启动服务器
./server.py
和来自不同主机的10个客户端并行:
for i in `seq 1 10`; do ./client.py 2>/dev/null 1>/dev/null & done
我将kill -SIGSTOP %1
发送给第一个客户端,我希望服务器成功地继续尝试发送数据,因为它不知道客户端已停止。 相反,服务器在尝试将数据发送到客户端1时会阻塞。如果客户端与服务器位于同一主机上,我可以理解行为:我们尝试写入数据,但是内核缓冲区已满,因此我们阻塞服务器,但客户端永远不会读取,因此永远不会释放缓冲区。 但是,如果客户端在不同的计算机上,则服务器主机的内核缓冲区应仅暂时充满,然后内核应通过网卡发送数据并释放它们。 那么,为什么我的服务器阻止了send
呼叫? 我尚未验证使用其他语言(例如C)时是否看到相同的行为
这很奇怪,因为1000个字符对于TCP来说很小。 我没有可用的Linux机器,但是在FreeBSD机器上,我可以通过TCP连接成功发送130000字节,在该TCP连接上,对等方在发送方阻塞之前已停止。 在Windows上超过1000000。
但是由于TCP是连接的协议,如果由于内部TCP堆栈队列已满而无法将其数据排队,则send
调用将阻塞。
问题的要点似乎是要创建SOCK_STREAM套接字(即TCP),然后突然终止客户端。 如Python Socket Programming HOWTO中所讨论的,在这种情况下预期会挂起。
TCP是可靠的协议,这意味着必须对每个传输的数据包进行确认。 如果接收方已死,则发送方将阻止等待该确认。 尝试设置超时,看看您的send
是否在预期时间之后引发了socket.timeout
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.