如何解决以太网传输字典时服务器端的JSON Loads错误?
问题描述
尝试通过以太网从客户端向服务器传输如下结构的字典:
data_transfer_dict={'Target':'', 'Mission':'', 'Optical/IR':'', 'Arm':'', 'Optical Zoom':0, 'Digital Zoom':0, 'Pitch':00000, 'Yaw':00000, 'Reset Camera':0, 'Target Selection':0, 'Take Screenshot':0}
尝试了JSON和pickle两种传输方式,其中JSON相关代码如下:
JSON代码
客户端侧
obj1.send_data(json.dumps(data_transfer_dict).encode('utf-8')) def send_data(self, data): # 原代码存在拼写错误,应为send_data而非data send if self.is_running: self.client_socket.send(data)
服务器侧
while True: count_bytes=self.client_socket.recv(2048) count=json.loads(count_bytes.decode('utf-8')) print("Dictionary: ", count)
客户端通过多线程持续发送数据,服务器在持续接收时触发错误:json.decoder.JSONDecodeError: Extra data: line 1 column 193 (char 192)
问题原因
TCP是流式协议,recv(2048)无法保证每次接收的都是单个完整的JSON数据包:可能一次性收到多个JSON对象拼接的字节流,也可能只收到一个JSON的部分数据。这两种情况都会导致json.loads解析失败,前者就会触发"Extra data"错误。
解决方案
需要给每个JSON数据包添加明确的边界标识,让服务器能准确拆分出每个完整的JSON对象,以下是两种常用实现方式:
方法1:换行符分隔数据包
客户端修改
发送时在JSON字符串末尾添加换行符,作为数据包的结束标记:
obj1.send_data((json.dumps(data_transfer_dict) + '\n').encode('utf-8'))
服务器修改
维护一个数据缓冲区,每次接收数据后追加到缓冲区,再按换行符拆分,只处理完整的JSON内容:
import json buffer = b'' while True: chunk = self.client_socket.recv(2048) if not chunk: break # 客户端断开连接 buffer += chunk # 循环拆分缓冲区中的完整JSON行 while b'\n' in buffer: json_bytes, buffer = buffer.split(b'\n', 1) try: count = json.loads(json_bytes.decode('utf-8')) print("Dictionary: ", count) except json.JSONDecodeError as e: print(f"解析错误: {e}")
方法2:发送数据包长度前缀
客户端修改
先发送JSON数据的字节长度(用固定4字节的大端整数),再发送实际的JSON内容:
json_str = json.dumps(data_transfer_dict) json_bytes = json_str.encode('utf-8') # 将数据长度转为4字节大端字节串 length_bytes = len(json_bytes).to_bytes(4, byteorder='big') # 先发送长度,再发送JSON数据 obj1.send_data(length_bytes + json_bytes)
服务器修改
先接收长度前缀,再根据长度接收完整的JSON数据:
import json while True: # 先接收4字节的长度前缀 length_bytes = self.client_socket.recv(4) if not length_bytes: break data_length = int.from_bytes(length_bytes, byteorder='big') # 接收指定长度的JSON数据 json_bytes = b'' while len(json_bytes) < data_length: chunk = self.client_socket.recv(data_length - len(json_bytes)) if not chunk: break json_bytes += chunk if len(json_bytes) == data_length: try: count = json.loads(json_bytes.decode('utf-8')) print("Dictionary: ", count) except json.JSONDecodeError as e: print(f"解析错误: {e}") else: print("接收到不完整的数据")
补充说明
- 换行符分隔法实现简单,适合文本类数据包;
json.dumps会自动转义字符串中的换行符,无需额外处理。 - 长度前缀法更可靠,能精确控制接收字节数,适配各种类型的数据包,避免拆分错误。
内容的提问来源于stack exchange,提问作者vidshah97
相关产品推荐
相关产品推荐

