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

跨Linux与Windows的Python Socket文件传输UnicodeDecodeError问题

跨系统文件传输编码错误修复方案

问题场景

将图片从树莓派(Linux客户端)传输至Windows笔记本(服务器)时,服务器端抛出编码错误:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 5: invalid start byte

同一Windows机器上运行两端脚本时,文件可正常传输。

错误原因

这是TCP粘包导致的:TCP是流式传输协议,客户端连续调用send()发送文件名、文件大小、二进制文件数据时,操作系统可能会将多个send()的内容合并为一个数据包发送。

  • 本地运行时,数据包拆分逻辑稳定,服务器能通过两次recv()分别获取完整的文件名和文件大小;
  • 跨网络传输时,网络延迟或系统缓冲区差异,导致服务器第二次recv()收到的是文件大小的部分数据+图片二进制开头数据(JPG文件开头包含0xff这类非UTF-8字节),解码时自然报错。

修正代码

客户端(client.py)

给文件名、文件大小添加明确的分隔符b"<SEP>",确保服务器能准确拆分数据:

import os
import socket

HOST = '192.168.2.80'  # 服务器IP
PORT = 3322
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    client.connect((HOST, PORT))
    print(f"STATUS_MSG: Connected-Successfully-To-Server-IP-{HOST}")
except:
    print("STATUS_MSG: Unable-To-Connect-To-Server")
    exit(0)

# 获取文件信息并添加分隔符
file_name = "image1.jpg"
file_size = os.path.getsize(file_name)
# 将文件名、文件大小用分隔符拼接后发送
client.send(f"{file_name}<SEP>{file_size}".encode())

# 发送文件数据
with open(file_name, "rb") as file:
    data = file.read()
    client.sendall(data)
    client.send(b"<END>")

client.close()

服务器端(server.py)

接收数据后按分隔符拆分,提取文件名和文件大小,再接收文件数据:

import os
import socket

HOST = '192.168.2.80'  # 笔记本私有IP
PORT = 3322
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))

print("STATUS_MSG: This-Is-Laptop")
print("STATUS_MSG: Awaiting-Connection-From-Client")
server.listen()

try:
    communication_socket, addrs_of_client = server.accept()
    print(f"STATUS_MSG: Connection-Established-To-Client-IP-{addrs_of_client}")
except:
    print("STATUS_MSG: Unable-To-Accept-Connection")
    exit(0)

# 接收并拆分文件名和文件大小
info_data = communication_socket.recv(1024).decode()
file_name, file_size = info_data.split("<SEP>")
file_size = int(file_size)
print(f"incoming file name = {file_name}")
print(f"incoming file size = {file_size}")

# 接收文件数据,按实际文件大小接收(比用<END>更可靠)
file_path = os.path.join("./recvt", file_name)
with open(file_path, "wb") as file:
    received_bytes = 0
    while received_bytes < file_size:
        data = communication_socket.recv(min(1024, file_size - received_bytes))
        if not data:
            break
        file.write(data)
        received_bytes += len(data)

print("File Received Successfully")
communication_socket.close()
server.close()

扩展多文件循环双向传输思路

  • 定义通信协议:给每个传输的数据包添加类型标识(比如"FILE_NAME"、"FILE_DATA"、"END_TRANSFER"、"REQUEST_SEND"等),明确双方的交互逻辑;
  • 循环交互:在两端添加循环逻辑,允许用户选择发送/接收文件,或者自动轮询待传输文件;
  • 双向通信:建立连接后保留socket连接,通过协议指令切换发送/接收角色,或建立两个独立socket分别处理发送和接收;
  • 异常处理:添加断连重连、文件哈希校验、超时机制,提升跨系统传输稳定性。

内容的提问来源于stack exchange,提问作者Ali Furqan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:25:26