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

屏幕日志项目截图传输异常:接收大小后仅获128KB,无大小可收全文件

问题分析与解决方案

核心问题1:客户端文件大小计算错误

你在客户端里用len(str(file))计算文件大小,这是错误的——str(file)会把字节对象转换成类似b'xxxx...'的字符串,这个字符串的长度和原始字节数据的长度完全无关。正确的做法是直接用len(file)获取字节数据的实际长度。

核心问题2:服务端未循环接收完整数据

TCP是流式协议,recv(size)不一定能一次性返回你请求的所有字节,它只会返回当前缓冲区里有的数据(默认缓冲区大小通常是128KB)。所以必须循环接收,直到累计拿到的字节数等于指定的大小。

修正后的客户端代码

import os
from datetime import datetime

import pygame
import pyscreenshot as ImageGrab
import socket


def take_screenshot():
    print("Taking screenshot...")

    image_name = f"screenshot-{str(datetime.now())}"
    image_name = image_name.replace(":", ";")
    screenshot = ImageGrab.grab(backend="mss", childprocess=False)

    filepath = f"./screenshots/{image_name}.png"

    screenshot.save(filepath)

    file = open(filepath, 'rb')
    b = file.read()
    file.close()
    os.remove(filepath)

    return b


def main():
    my_socket = socket.socket()
    my_socket.connect(("127.0.0.1", 8820))

    clock = pygame.time.Clock()
    file = take_screenshot()
    # 修正:直接取字节数据的长度
    file_size = len(file)
    print(file_size)
    # 发送固定10位的大小编码 + 原始字节数据
    my_socket.send(str(file_size).zfill(10).encode() + file)

    my_socket.close()

if __name__ == '__main__':
    main()

修正后的服务端代码

import os
from datetime import datetime
import MySQLdb as mysql
import pygame
import socket


def server_setup():
    S_socket = socket.socket()
    print("Server is up and running")
    return S_socket


def client_bind():
    global server_socket
    print("turning on server")
    server_socket.bind(("0.0.0.0", 8820))
    server_socket.listen(1)
    (client_socket, client_address) = server_socket.accept()
    print(client_address[0])
    return client_socket, client_address


server_socket = server_setup()
client_socket, client_address = client_bind()

image_name = f"screenshot-{str(datetime.now())}"
image_name = image_name.replace(":", ";")
filepath = f"./screenshots/{image_name}.png"

# 接收文件大小
size_data = client_socket.recv(10)
size = int(size_data.decode())
print(f"Expected file size: {size}")

# 循环接收完整数据
received_data = b''
while len(received_data) < size:
    # 每次接收剩余的字节数,或者缓冲区最大容量
    chunk = client_socket.recv(min(size - len(received_data), 4096))
    if not chunk:
        # 连接断开,提前结束
        break
    received_data += chunk

print(f"Received {len(received_data)} bytes")
with open(filepath, 'xb') as new_file:
    new_file.write(received_data)

client_socket.close()
server_socket.close()

额外说明

  • 服务端里的函数名client_blind是笔误,已修正为client_bind。
  • 循环接收时用min(size - len(received_data), 4096)可以避免每次请求过大的缓冲区,同时保证高效接收剩余数据。
  • 如果客户端意外断开,recv会返回空字节串,这里加了判断可以提前终止接收,避免无限等待。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:40:52