Python Socket传图片报错:struct.error: unpack需4字节缓冲区
问题分析与解决方案
错误原因
TCP是流式传输协议,conn.recv(n)调用仅会返回当前缓冲区中可用的数据,不会保证恰好返回n字节。你的服务器直接用buf = conn.recv(4)后就尝试unpack,当网络波动或数据分片时,可能只收到不足4字节的内容,触发struct.error。
修复后的服务器代码
import socket import struct HOST = "127.0.0.1" PORT = 65432 def recv_all(conn, length): """接收指定长度的字节数据,确保拿到完整内容""" data = b'' while len(data) < length: chunk = conn.recv(length - len(data)) if not chunk: # 连接中断,返回已接收的部分(或抛出异常) return None data += chunk return data with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print(f"Connected by {addr}") # 先接收4字节的长度信息 len_buf = recv_all(conn, 4) if not len_buf: print("连接提前中断") exit() length, = struct.unpack('!I', len_buf) # 接收完整的图片数据 img_data = recv_all(conn, length) if not img_data: print("图片数据接收不完整") exit() # 将接收的图片保存到本地 with open('received_image.jpeg', 'wb') as fp: fp.write(img_data) print(f"图片接收完成,大小:{length}字节")
关键修改点
- 新增
recv_all辅助函数:循环调用recv,直到凑够指定长度的字节,彻底解决TCP流式传输的分片问题 - 移除不必要的外层
while True:原代码会在接收完一张图片后再次尝试读取长度,导致无意义的等待或报错 - 增加连接中断处理:当客户端提前断开连接时,能及时终止流程并给出提示
- 补充图片保存逻辑:接收完成后将数据写入文件,完成完整的传输闭环
客户端代码优化建议
客户端代码基本可用,但可以增加文件存在性检查,避免因文件路径错误导致的空数据传输:
import socket import struct import os HOST = "127.0.0.1" PORT = 65432 img_path = 'test-images/hummingbird-1.jpeg' if not os.path.exists(img_path): print(f"错误:文件 {img_path} 不存在") exit() with open(img_path, 'rb') as fp: img_byte = fp.read() with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((HOST, PORT)) length = len(img_byte) s.sendall(struct.pack('!I', length)) s.sendall(img_byte) print("图片发送完成")
内容的提问来源于stack exchange,提问作者Resting Platypus
相关产品推荐
相关产品推荐

