Python socket中recv(2)未按预期接收2字节的原因咨询
问题:Socket recv(2)为何每次只接收1字节?
我写了一段Python Socket服务端代码:
import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_address = ('127.0.0.1', 8000) server_socket.bind(server_address) server_socket.listen() try: connection, client_address = server_socket.accept() print(f'I got a connection from {client_address}!') buffer = b'' while buffer[-2:] != b'\r\n': data = connection.recv(2) if not data: break else: print(f'I got data: {data}!') buffer = buffer + data print(f"All the data is: {buffer}") finally: server_socket.close()
我预期的运行输出是:
I got a connection from ('127.0.0.1', 49721)! I got data: b'te'! I got data: b'st'! I got data: b'in'! I got data: b'g1'! I got data: b'\r\n'! All the data is: b'testing1\r\n'
但实际得到的输出是:
I got a connection from ('127.0.0.1', 49721)! I got data: b't'! I got data: b'e'! I got data: b's'! I got data: b't'! I got data: b'i'! I got data: b'n'! I got data: b'g'! I got data: b'1'! I got data: b'\r\n'! All the data is: b'testing1\r\n'
已知recv方法应该从客户端套接字接收最多2字节数据并返回bytes对象,为什么实际没按预期工作?是不是我理解错了什么?
解答
核心问题出在对TCP协议和recv方法的理解偏差:
recv(n)中的n是最大接收字节数,而非固定接收字节数。TCP是流式协议,数据以连续字节流的形式传输,不存在天然的消息边界。操作系统会根据套接字接收缓冲区的当前数据量、网络传输的分段情况来决定返回多少字节——哪怕你指定了2,只要缓冲区里有1字节可读,recv就会立刻返回这1字节,不会等待凑够2字节再返回。实际输出中每次返回1字节,大概率是因为客户端发送数据时是逐个字节发送,或者网络层将数据拆分为单字节的IP包传输。但无论哪种情况,TCP仅保证最终接收的字节顺序正确,不保证数据会按你期望的批次到达。
如果需要实现“每次至少接收指定长度数据”的逻辑,需要自行封装循环接收的逻辑,示例如下:
def recv_exact(conn, size): buffer = b'' while len(buffer) < size: chunk = conn.recv(size - len(buffer)) if not chunk: # 客户端提前断开连接 return buffer buffer += chunk return buffer
不过要注意,这种逻辑仅适用于已知固定接收长度的场景。像你原代码中以\r\n作为结束标记的协议,仍需保留原有的循环方式——因为无法预知结束标记前的数据长度,也没法强制数据按固定批次到达。
内容的提问来源于stack exchange,提问作者toxfu
相关产品推荐
相关产品推荐

