了解套接字行为:为什么 Socket.recv() 在没有发送数据的情况下停止
Python 套接字与 TCP 连接一样,表现为数据流在客户端和服务器之间流动。本文深入探讨了修改数据传输后,socket.recv()调用无法返回数据的原因。
Echo Server 示例
考虑官方文档中的 Python echo 服务器示例。该服务器侦听传入连接、接收数据并将其回显给客户端。以下代码片段复制了原始服务器行为:
import socket HOST = '' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print('Connected by', addr) while True: data = conn.recv(1024) if not data: break conn.sendall(data) conn.close()
更改服务器行为
将代码修改为不将数据发送回客户端时会出现此问题:
while True: data = conn.recv(1024) if not data: break conn.close()
在这段修改后的代码中,while循环不断地从客户端接收数据,但服务器却从不发送数据 后退。这会导致客户端在 socket.recv() 调用处无限期地停止。
理解通信流程
TCP 套接字不维护一对一关系不同端点上的发送和接收呼叫之间。相反,协议定义了通信规则。在这种情况下,原始的回显服务器实现了一个规则,即服务器将回显接收到的数据,直到客户端关闭连接。
当服务器行为发生更改时,规则实际上已被修改。服务器现在只接收数据并丢弃它,直到客户端关闭连接。服务器永远不会将数据发送回客户端。
调整客户端行为
要使用修改后的服务器,客户端必须调整其行为。由于服务器不再主动发送数据,客户端认为收到回数据表明连接已完成。为了实现这一点,客户端应该关闭其连接的传出端,以向服务器发出信号已完成发送数据。然后,客户端可以执行多个 recv 调用来处理传入数据的任何潜在碎片。
更新的代码
下面是服务器和客户端的更新代码,遵守修改后的规则通信:
服务器:
import socket HOST = '' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print('Connected by', addr) while True: data = conn.recv(1024) if not data: break conn.sendall(b'ok') conn.shutdown(socket.SHUT_WR) conn.close()
客户端:
import socket HOST = 'localhost' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.sendall(b'Hello, world') s.shutdown(socket.SHUT_WR) data = b'' while True: buf = s.recv(1024) if not buf: break data += buf s.close() print('Received', repr(data))
通过了解基于流的本质TCP套接字并相应地调整通信规则,可以解决socket.recv()在没有数据的情况下停止的问题已发送。
以上是当服务器不发回数据时,为什么 `socket.recv()` 会停止?的详细内容。更多信息请关注PHP中文网其他相关文章!