Python WebSocket服务端报错unpack requires a buffer of 1 bytes如何解决
问题解决方法
核心错误原因
- 第一,WebSocket负载长度解析规则不符合协议规范,struct格式符使用错误
WebSocket RFC6455规定的负载长度编码规则:当首字节掩码后的长度值为126时,后续2字节为大端序的16位无符号整数,作为实际负载长度
当首字节掩码后的长度值为127时,后续8字节为大端序的64位无符号整数,作为实际负载长度
你当前代码用struct.unpack('B', data)解析,B对应单字节无符号整数,传入2字节/8字节的缓冲区自然会触发长度不匹配的错误,127分支的+=写法也是完全错误的逻辑。 - 第二,直接调用
socket.recv(n)不保证返回恰好n字节数据,TCP是流协议,单次recv可能返回小于请求长度的字节,若未做补收逻辑就直接解析,同样会触发缓冲区长度不足的错误。
修复方案
首先实现一个确保收满指定字节的辅助方法:
def recv_full(self, n): data = b'' while len(data) < n: chunk = self.conn.recv(n - len(data)) if not chunk: # 连接异常断开,可根据业务需求调整异常处理逻辑 self.close_handshake(1006) return data
然后修正parse_frame方法的长度解析逻辑:
import struct def parse_frame(self): # 收满2字节基础帧头 data = self.recv_full(2) FIN = (data[0] >> 7) & 1 RSV1 = (data[0] >> 6) & 1 RSV2 = (data[0] >> 5) & 1 RSV3 = (data[0] >> 4) & 1 OPCODE = data[0] & 0xf MASK = (data[1] >> 7) & 1 if not MASK: self.close_handshake(1002) PAYLOAD_LENGTH = data[1] & 0x7f if PAYLOAD_LENGTH == 126: # 解析2字节大端序16位无符号整数作为实际长度 len_data = self.recv_full(2) PAYLOAD_LENGTH = struct.unpack('!H', len_data)[0] elif PAYLOAD_LENGTH == 127: # 解析8字节大端序64位无符号整数作为实际长度 len_data = self.recv_full(8) PAYLOAD_LENGTH = struct.unpack('!Q', len_data)[0] MASKING_KEY = self.recv_full(4) PAYLOAD_DATA = self.recv_full(PAYLOAD_LENGTH) PAYLOAD_DATA = self.unmask(PAYLOAD_DATA, MASKING_KEY) return OPCODE, PAYLOAD_DATA
关键修正点说明
struct.unpack的格式符!H代表大端序16位无符号短整数,!Q代表大端序64位无符号长整数,完全匹配WebSocket协议的长度编码规则- 新增的
recv_full方法循环接收数据直到凑齐指定长度,规避TCP流协议单次recv数据不足的问题 - 移除了127分支错误的
+=运算逻辑,直接使用解析出的64位整数作为实际负载长度
内容的提问来源于stack exchange,提问作者user15832679
相关产品推荐
相关产品推荐

