当保持客户端套接字打开以发送多条消息时,为什么在消息出现大延迟时程序会出错



有一个服务器监听连接。客户端套接字连接到服务器,并在关闭服务器之前在循环中多次调用sendall()。但是,如果任何迭代需要一段时间,则会出现ConnectionAbortedError

有一个从0-9开始的循环,在每次迭代中,都有一个使用客户端套接字的sendall()。为了创建延迟,我添加了一个伪while循环,它只是增加一些变量。

服务器代码的相关部分

with socket.socket() as s:
s.bind(('127.0.0.1', 65432))
s.listen()
while True:
connection, address = s.accept()
with connection:
data = connection.recv(72)
print('Client says "{}"'.format(data))

客户端代码

with socket.socket() as s:
s.connect((host, port))
for i in range(10):
s.sendall(bytes("message {}".format(i+1), encoding='utf-8'))
if i+1 == 3:
count = 0
while count < 12000:
count += 1

while循环中计数的一个小限制(如500)可以很好地工作。然而,超过5000似乎会导致错误。我不清楚他们为什么给出不同的结果。

您的服务器代码不正确。您应该使用threading或任何其他技术来为多个客户端连接提供服务。这里发生了什么:

1) 服务器接受第一个套接字

2) 服务器接收72字节

3) 连接已关闭,因为with操作员将其关闭

4) 服务器进入下一个accept循环

您的服务器从客户端只读取一次,最多接收72个字节,然后关闭连接。如果客户端能够足够快地发送所有10条消息,它就不会出错。阅读关于Nagle算法:

如果连接上以前传输的任何数据未被确认,则当用户收到新的传出数据时,禁止发送新的TCP段。

您的服务器永远不会接收到所有消息(总共91字节),但如果客户端发送了所有消息,则不会出错。

对服务器的一个小更改确保它通过等待直到客户端关闭连接来接收所有数据(无论延迟):

with connection:
while True:
data = connection.recv(72)
if not data: break # empty data means client closed connection.
print('Client says "{}"'.format(data))

这仍然不会逐个接收消息。TCP是一种流协议,因此消息被连接在一起。您需要添加缓冲区和一种仅从中提取完整消息的方法。示例(Python 3.6+):

客户端.py

import socket
host = '127.0.0.1'
port = 65432
with socket.socket() as s:
s.connect((host, port))
for i in range(10):
# Use newline as message delimiter.
s.sendall(f'message {i+1}n'.encode())

服务器.py

import socket
with socket.socket() as s:
s.bind(('127.0.0.1', 65432))
s.listen()
while True:
connection, address = s.accept()
with connection:
data = b''
while True:
chunk = connection.recv(16)
if not chunk: break # client closed connection
data += chunk # buffer input
while b'n' in data: # break off messages and display
msg,_,data = data.partition(b'n')
print(f'Client says "{msg.decode()}"')
if data:
print(f'Incomplete message: {data}')

输出:

Client says "message 1"
Client says "message 2"
Client says "message 3"
Client says "message 4"
Client says "message 5"
Client says "message 6"
Client says "message 7"
Client says "message 8"
Client says "message 9"
Client says "message 10"

最新更新