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

Python跨PC Socket文件传输UTF-8编码异常问题求助

解决跨PC文件传输中UTF-8解码异常的问题

你遇到的问题本质是TCP流式传输的部分数据接收问题——本地运行时网络延迟极低,recv(1024)能一次性拿到完整的文件名字节,解码自然正常;但跨PC网络传输时,TCP会把数据拆分成多个数据包发送,服务端第一次recv可能只拿到部分字节,直接用utf-8解码就会因为字节不完整抛出异常(比如截断了UTF-8的多字节字符)。

核心原因拆解

TCP是面向流的协议,它不保证一次recv能获取对等方sendall发送的全部数据。当文件名的字节数超过单次接收缓存,或者网络主动拆分了数据包,服务端拿到的就是不完整的字节序列,UTF-8解码必然失败。

解决方案:先传长度,再传内容

我们可以通过先发送文件名的字节长度,再发送文件名内容的方式,让服务端明确知道需要接收多少字节,确保拿到完整数据后再解码。

修改后的客户端代码

import socket
import struct

HOST = "服务端实际IP地址"
PORT = 你的端口号
filename = "要传输的文件名.txt"

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.connect((HOST, PORT))
    # 1. 将文件名转为UTF-8字节
    filename_bytes = filename.encode('utf-8')
    # 2. 把字节长度打包为4字节的二进制数据(大端模式,确保跨平台兼容)
    length_packed = struct.pack('!I', len(filename_bytes))
    # 3. 先发送长度,再发送文件名内容
    sock.sendall(length_packed)
    sock.sendall(filename_bytes)
    print(f"已发送文件名字节:{filename_bytes}")

修改后的服务端代码

import socket
import struct

HOST = "0.0.0.0"  # 监听所有网卡
PORT = 你的端口号

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"连接来自 {addr}")
        # 1. 先接收4字节的长度数据
        length_data = conn.recv(4)
        if not length_data:
            print("未接收到文件名长度数据")
            exit()
        # 2. 解包得到文件名的字节长度
        filename_length = struct.unpack('!I', length_data)[0]
        # 3. 循环接收,直到拿到完整的文件名字节
        filename_bytes = b''
        while len(filename_bytes) < filename_length:
            # 每次接收剩余长度和1024的较小值,避免浪费缓存
            chunk = conn.recv(min(filename_length - len(filename_bytes), 1024))
            if not chunk:
                print("连接中断,未接收完整文件名")
                break
            filename_bytes += chunk
        # 4. 解码文件名并处理异常
        try:
            filename = filename_bytes.decode('utf-8')
            print(f"接收到的文件名:{filename}")
        except UnicodeDecodeError as e:
            print(f"UTF-8解码失败:{e}")

额外注意事项

  • 确保客户端和服务端使用完全一致的编码格式(这里统一用utf-8),避免编码不匹配导致的隐性错误。
  • 加入UnicodeDecodeError捕获,可以在解码失败时给出友好提示,而不是直接崩溃。
  • 如果需要传输超大文件名,可以把长度打包格式换成!Q(8字节),支持最大16EB的字节长度,完全覆盖日常需求。

内容的提问来源于stack exchange,提问作者Donghee Min

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:19:13