如何在Python Socket中接收来自服务器的完整数据
Python Socket 接收完整数据时卡顿的解决办法
你的代码卡顿核心原因是:recv() 方法在没有数据且服务器未关闭连接时会一直阻塞等待。只有当服务器主动断开 socket 连接时,recv() 才会返回空字节串触发 break,这就导致程序卡在循环里无限等待数据。
下面是几种实用的解决思路:
方案1:约定数据长度(推荐)
让服务器先发送数据的总字节数,客户端先读取这个长度,再精准接收对应字节的数据,从根源避免无意义阻塞。
def readReply(self): recv_data = b'' # 先接收数据长度(假设用4字节大端序存储长度) len_data = self.client_socket.recv(4) if not len_data: return b'' total_len = int.from_bytes(len_data, byteorder='big') # 循环接收直到拿到全部数据 while len(recv_data) < total_len: # 每次接收剩余长度和1024的较小值,避免浪费资源 chunk = self.client_socket.recv(min(1024, total_len - len(recv_data))) if not chunk: # 服务器提前断开,返回已接收的部分数据 break recv_data += chunk return recv_data
注意:服务器端需要对应修改逻辑——先把数据长度转成4字节大端序发送,再发送实际内容。
方案2:用分隔标记判断结束
如果无法修改服务器逻辑,可约定一个特定的结束标记(比如 b'__END__'),客户端接收时检查是否包含该标记,找到后立即停止循环。
def readReply(self): recv_data = b'' delimiter = b'__END__' while True: chunk = self.client_socket.recv(1024) if not chunk: break recv_data += chunk # 检查是否收到结束标记 if delimiter in recv_data: # 截断掉结束标记,返回有效数据 recv_data = recv_data[:-len(delimiter)] break return recv_data
缺点:如果数据本身包含约定的分隔符会导致误判,仅适合数据内容可控的场景。
方案3:设置Socket超时
给Socket设置超时时间,超过指定时长就停止接收,避免无限阻塞。
def readReply(self): recv_data = b'' # 设置5秒超时,可根据实际传输速度调整 self.client_socket.settimeout(5) try: while True: chunk = self.client_socket.recv(1024) if not chunk: break recv_data += chunk except TimeoutError: # 超时后返回已接收的数据 pass # 恢复默认的阻塞模式(可选) self.client_socket.settimeout(None) return recv_data
缺点:如果数据传输耗时超过超时时间,会提前终止接收,适合对数据完整性要求不高或能预估传输时长的场景。
内容的提问来源于stack exchange,提问作者Bugsfounder
相关产品推荐
相关产品推荐

