【问题标题】:Sending multiple images with socket使用套接字发送多个图像
【发布时间】:2020-03-25 10:50:56
【问题描述】:

在使用 Python 制作 VNC 的雄心勃勃的尝试中,我试图不断地将一个用户(服务器)的屏幕截图发送到另一个用户(客户端)。经过几个小时的尝试并达到鲍尔默的巅峰,我成功地做到了。但是,现在我的问题是发送多个图像,它们是连续的流。我首先尝试将所有二进制数据写入一个文件,但没有成功。当第二张图片打开时,它崩溃了。我认为这可能是因为二进制数据以某种方式损坏了,所以我尝试为每个图像创建一个新文件,但我遇到了同样的问题。我知道 Tcp 是一个恒定的数据流,因此很难知道第一个图像的结束和下一个图像的开始,但是通过创建另一个文件,我认为我会很好。

非常感谢您在解决此问题和/或提高效率方面的任何帮助 :)

服务器端:

import socket
from PIL import Image, ImageGrab

PORT = 10007
HOST = '127.0.0.1'

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:

        counter = 3

        while counter > 0:
            image = ImageGrab.grab(bbox=None)
            image.save('test.png')

            f = open('test.png', 'rb')

            l = f.read(1024)

            while (l):
                conn.send(l)
                l = f.read(1024)

            f.close()
            print('Done sending curr image')
            counter -= 1

conn.close()

客户端:

import socket
from PIL import Image

HOST = '127.0.0.1'
PORT = 10007


with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))


    counter = 1

    while counter != 3:
        fname = 'image' + str(counter) + '.png'

        with open(fname, 'wb') as file:

            print('file opened')

            while True:
                data = s.recv(1024)
                if not data:
                    break
                else:
                    file.write(data)

        file.close()
        currImg = Image.open(fname)
        currImg.show()
        counter += 1






s.close()

【问题讨论】:

    标签: python-3.x sockets tcp python-sockets


    【解决方案1】:

    您的接收者不知道一个文件何时结束而下一个文件何时开始。解决这个问题的最简单方法是在发送每个文件之前将文件的长度(可能是一个 4 字节的无符号值)发送给接收方。然后接收方可以读取长度,读取文件,读取长度,读取文件,...

    为了提高效率,您可以停止将文件数据保存到两端的实际文件中,而是将其保存到(显然,从中读取)内存缓冲区。有关如何执行此操作的说明,请参阅 this answer。在 Python 3 中,您似乎会使用 BytesIO 模块。

    另一个改进是仅发送自上次发送以来已更改的屏幕部分的图像数据。为此,您需要弄清楚如何将当前捕获与前一个捕获进行比较。对于第一遍,您可以使用PIL.ImageChops.difference,然后使用PIL.Image.getbbox,然后仅对当前捕获的该区域进行编码和发送。为此,发送者不仅要告诉接收者 PNG 的大小,还要告诉接收者在输出屏幕图像中应该绘制新图像补丁的位置。因此,除了大小和编码的图像数据之外,您还需要发送一个位置。

    【讨论】:

      猜你喜欢
      • 2012-08-09
      • 2015-01-08
      • 1970-01-01
      • 2013-12-31
      • 2016-09-12
      相关资源
      最近更新 更多