You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Crypto库加密文件时接收端解码文件大小遇UnicodeDecodeError求助

文件加密传输中接收端解码文件大小失败的解决方法

问题根源

TCP是流式传输协议,发送端连续调用send的内容会被操作系统合并为一个或多个TCP报文发送,接收端的recv(1024)会读取当前缓冲区所有可用数据,并非严格对应单个send的内容。你的代码中,第一次recv可能已经把文件名、部分文件大小甚至加密数据一并读走,导致第二次recv拿到的是加密后的二进制数据,无法用UTF-8解码,触发UnicodeDecodeError。

解决方案

需要通过明确的边界标识或固定长度传输来区分不同数据段,确保接收端能准确读取每个字段。

方案1:使用分隔符区分数据段

在每个数据字段末尾添加唯一分隔符(比如\n),接收端按分隔符读取完整字段。

发送端修改代码

# 发送文件名,末尾加换行符作为分隔
client.send(b'file.txt\n')
# 发送文件大小,末尾加换行符
client.send(f"{file_size}\n".encode())
# 发送加密数据
client.sendall(encrypted)
# 发送结束标记
client.send(b'<END>')
client.close()

接收端修改代码

先实现一个按分隔符读取完整数据的辅助函数:

def recv_until(conn, delimiter):
    buffer = b''
    while True:
        chunk = conn.recv(1024)
        if not chunk:
            return None
        buffer += chunk
        if delimiter in buffer:
            data, _ = buffer.split(delimiter, 1)
            return data

# 读取文件名
file_name = recv_until(client, b'\n').decode()
print(file_name)
# 读取文件大小并转换为整数
file_size = int(recv_until(client, b'\n').decode())
print(file_size)

# 读取加密数据直到结束标记
encrypted_data = b''
while True:
    chunk = client.recv(1024)
    if b'<END>' in chunk:
        encrypted_data += chunk.split(b'<END>')[0]
        break
    encrypted_data += chunk

方案2:固定长度传输(更可靠)

用struct模块将数据长度打包为固定字节数(比如4字节无符号整数),先发送长度,再发送对应长度的数据。

发送端修改代码

import struct

# 发送文件名:先传长度,再传内容
name_bytes = b'file.txt'
client.send(struct.pack('!I', len(name_bytes)))  # 打包为大端字节序的4字节整数
client.send(name_bytes)

# 发送文件大小:打包为4字节整数
client.send(struct.pack('!I', file_size))

# 发送加密数据和结束标记
client.sendall(encrypted)
client.send(b'<END>')
client.close()

接收端修改代码

import struct

# 读取文件名长度(4字节)
name_len_data = client.recv(4)
name_len = struct.unpack('!I', name_len_data)[0]
# 读取对应长度的文件名
file_name = client.recv(name_len).decode()
print(file_name)

# 读取文件大小(4字节)
file_size_data = client.recv(4)
file_size = struct.unpack('!I', file_size_data)[0]
print(file_size)

# 读取加密数据直到结束标记
encrypted_data = b''
while True:
    chunk = client.recv(1024)
    if b'<END>' in chunk:
        encrypted_data += chunk.split(b'<END>')[0]
        break
    encrypted_data += chunk

内容的提问来源于stack exchange,提问作者Dulitha Bandaranayake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:47:50