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

Python屏幕共享Socket项目跨设备运行pickle数据截断报错求解

错误根源

你当前的错误是TCP流接收逻辑判断错误导致的:

  • 你用if len(dataBin_) < BUFFER: break作为接收完一帧数据的判断条件,这个逻辑仅在本地环回传输时成立,本地传输数据不会被拆分成多个小于BUFFER的包。
  • 跨网络传输时,TCP会根据网络情况拆包,很可能出现某次recv返回的数据长度小于BUFFER但实际整帧数据还没传完的情况,你提前终止了接收,拿到的pickle数据不完整,就会触发_pickle.UnpicklingError: pickle data was truncated错误。

解决方案

在发送数据前先发送固定长度的头部,告知接收端当前帧的总长度,接收端按指定长度接收完整数据后再做反序列化即可解决问题。

修改后Client.py代码

import socket, pickle, time, cv2, struct
import pyautogui
import numpy as np

# Constants
BUFFER = 1024 * 8
ADDR = '192.168.20.4'
PORT = 9090

# Connect to Server
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((ADDR, PORT))

# Cool down time
time.sleep(2)

# Stream Screen
while True:
    screen = np.array(pyautogui.screenshot())
    screenGray = cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY)
    lowResGrayImg = cv2.resize(screenGray, (1280,800), fx=0, fy=0, interpolation=cv2.INTER_CUBIC)

    if client.recv(1) == b's':
        # 序列化数据
        data = pickle.dumps(lowResGrayImg)
        # 打包数据长度为4字节固定头部
        head = struct.pack('I', len(data))
        # 先发送头部再发送数据,sendall确保数据全部发出
        client.sendall(head)
        client.sendall(data)

修改后Server.py代码

import socket, pickle, cv2, struct

# CONSTANTS
BUFFER = 1024 * 8
ADDR = '192.168.20.4'
PORT = 9090

# Create Server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ADDR, PORT))
server.listen(1)

def recv_exact(client, length):
    # 精确接收指定长度的字节数据,避免提前终止
    data = b''
    while len(data) < length:
        chunk = client.recv(min(BUFFER, length - len(data)))
        if not chunk:
            raise ConnectionError("客户端断开连接")
        data += chunk
    return data

# Display Image
def display(client):
    while True:
        # Get Data
        client.send(b's')
        # 先接收4字节头部,获取数据总长度
        head = recv_exact(client, 4)
        data_len = struct.unpack('I', head)[0]
        # 按长度接收完整的pickle数据
        dataBin = recv_exact(client, data_len)

        # Display Screen
        screen = pickle.loads(dataBin)

        cv2.imshow('Screen', screen)
 
        cv2.waitKey(1)

# Accept Connections
client, address = server.accept()
print(f'{address[0]} is connected!')

print(client.recv(10))
display(client)

额外排查项

如果修改后仍有问题可检查以下内容:

  • 服务端和客户端Python大版本保持一致,不同大版本的pickle序列化格式不兼容
  • 两端防火墙没有拦截9090端口的数据包
  • 网络延迟过高时可适当调大BUFFER值减少接收循环次数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 05:15:03