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

Python Socket跨机器传输截图时多图合并为单个文件的问题

问题分析

跨机器传输时截图合并为单个大文件的核心原因是TCP粘包,加上原代码的分隔逻辑存在漏洞:

  • TCP是流式协议,跨机器网络延迟会导致服务器发送的图片数据与分隔符b"full"粘在一起,客户端无法正确识别每个图片的边界
  • 客户端判断逻辑错误:当收到包含b"full"的粘包数据时,会直接写入文件,且b"full"可能被遗留到下一次接收循环,导致后续图片数据被追加到同一文件
解决方案

采用固定长度的头部+数据体的传输协议,先发送图片数据的字节长度(用struct打包为固定4字节),再发送图片内容,从根本上避免粘包问题。同时优化服务端流程,无需将截图保存到本地磁盘,直接在内存中处理。

修改后的服务端代码

import time
import pyautogui
import struct
from socket import *
from io import BytesIO

host = "192.168.43.79"
port = 4446

s = socket(AF_INET, SOCK_STREAM)
s.bind((host, port))
print("Listening for connections.. ")
q, addr = s.accept()

i = 0
while True:
    # 截图直接存入内存字节流,无需写入磁盘
    screenshot = pyautogui.screenshot()
    img_byte_arr = BytesIO()
    screenshot.save(img_byte_arr, format='JPEG')
    img_byte_arr = img_byte_arr.getvalue()
    
    # 发送图片长度(打包为4字节大端整数)
    img_len = struct.pack('!I', len(img_byte_arr))
    q.send(img_len)
    # 发送图片数据
    q.sendall(img_byte_arr)
    
    i += 1
    time.sleep(0.3)

修改后的客户端代码

import struct
from socket import *

host = "192.168.43.79"
port = 4446

s = socket(AF_INET, SOCK_STREAM)
s.connect((host, port))

i = 0
while True:
    # 先接收4字节的图片长度
    len_data = s.recv(4)
    if not len_data:
        break  # 连接断开
    img_len = struct.unpack('!I', len_data)[0]
    
    # 接收指定长度的图片数据
    received_len = 0
    with open(f"{i}s.jpg", "wb") as f:
        while received_len < img_len:
            chunk = s.recv(min(4096, img_len - received_len))
            if not chunk:
                break
            f.write(chunk)
            received_len += len(chunk)
    i += 1
关键优化点
  • 避免磁盘IO:服务端用BytesIO将截图直接转为内存字节流,无需保存本地文件,提升传输效率
  • 明确数据边界:通过struct打包固定长度的头部,客户端可精准计算需要接收的图片数据量,彻底解决粘包问题
  • 健壮的接收逻辑:客户端按剩余需要接收的长度调整每次recv的大小,确保数据完整接收

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:50:32