使用Python Socket传输图片时遇UnicodeDecodeError问题求助
解决Socket传输图片时的UnicodeDecodeError错误
错误原因
出现UnicodeDecodeError是因为TCP粘包:客户端连续发送文件名、文件大小和图片数据时,服务端的recv(1024)可能一次性接收了多个数据块(比如文件名+部分图片数据),而图片是二进制数据,无法用UTF-8解码,导致报错。此外代码还有几处语法和逻辑错误。
修复方案
1. 解决粘包问题
用分隔符标记元数据(文件名、文件大小)的结束,确保服务端能准确拆分不同类型的数据,避免二进制图片数据混入文本解码流程。
2. 修正代码错误
- 服务端的
file-bytes是笔误,应为file_bytes - 统一结束标记的格式,避免匹配失败
- 进度条更新基于实际接收的字节数,而非固定值
修复后的服务端代码
import socket import tqdm server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(("localhost", 9999)) server.listen() client, addr = server.accept() # 循环接收文件名,直到拿到分隔符 file_name = b"" while b"<SEP>" not in file_name: file_name += client.recv(1024) file_name = file_name.decode().replace("<SEP>", "") # 循环接收文件大小,直到拿到分隔符 file_size = b"" while b"<SEP>" not in file_size: file_size += client.recv(1024) file_size = int(file_size.decode().replace("<SEP>", "")) file = open(file_name, "wb") file_bytes = b"" done = False progress = tqdm.tqdm(unit="B", unit_scale=True, unit_divisor=1000, total=file_size) while not done: data = client.recv(1024) # 检测结束标记并截断数据 if b"<END>" in data: file_bytes += data[:data.find(b"<END>")] done = True else: file_bytes += data # 更新实际接收的字节数 progress.update(len(data)) file.write(file_bytes) file.close() client.close() server.close()
修复后的客户端代码
import os import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(("localhost", 9999)) file_path = "image.png" file_name = "received_image.png" file_size = os.path.getsize(file_path) # 发送文件名+分隔符,避免粘包 client.send(f"{file_name}<SEP>".encode()) # 发送文件大小+分隔符 client.send(f"{file_size}<SEP>".encode()) # 发送图片数据 with open(file_path, "rb") as file: data = file.read() client.sendall(data) # 发送结束标记 client.send(b"<END>") client.close()
关键说明
- 用
<SEP>作为元数据的结束标记,确保服务端能准确拆分文本数据和二进制图片数据 - 结束标记
<END>在图片数据发送完成后发送,服务端检测到标记即停止接收 - 进度条更新使用
len(data),保证进度与实际接收字节数一致
内容的提问来源于stack exchange,提问作者Isuru Prasad
相关产品推荐
相关产品推荐

