【问题标题】:Sending an image over a socket as bytes通过套接字以字节形式发送图像
【发布时间】:2016-12-10 13:21:30
【问题描述】:

我想将服务器的屏幕截图发送给客户端,为了做到这一点,我想将图像作为字节发送,并将其拆分为多个部分,每个部分的长度为 1024。

首先,程序做了很多事情,它还发送文件、时间等。所以客户端需要告诉服务器他/(它)?想要一个图像,所以他首先发送'Img',然后服务器返回'Img',当客户端收到'Img'时,他开始监听所有部分,服务器开始发送所有部分,当最后一部分发送,服务器发送'Sent'。

到目前为止我的代码:Client.py:

def listen_for_image():
    bytes_data = socket_con.recv(1024)
    part = bytes_data
    i = 1
    print("Part #", str(i))
    while part.decode() != 'Sent':
        part = socket_con.recv(1024)
        bytes_data += part
        i += 1
        print("Part #", str(i))
    return bytes_data


    socket_con.send('Img')
    data_back = socket_con.recv(1024)
    if data_back.decode() == 'Img':
        bytes_full_data = listen_for_image()
        img = Image.frombytes('RGB', (1366, 768), bytes_full_data)
        img.save('newimg.jpg')

Server.py:

def send_screen_shot():
    con.send('Img'.encode())
    image = ImageGrab.grab()
    start = 0
    end = 1024
    while end < len(image.tobytes()):
        con.send(image.tobytes()[start:end])
        start = end + 1
        end += 1024
    con.send("Sent".encode())


if con.recv(1024).decode() == 'Img':
        send_screen_shot()

请注意,我的程序做得更多,所以这不是完整的代码,只是需要的部分,如果您需要其他内容,请询问:)

我的代码的问题是在客户端出现错误:

Traceback (most recent call last):
  File "C:/Users/dodob/PycharmProjects/untitled/client.py", line 33, in <module>
    bytes_full_data = listen_for_image()
  File "C:/Users/dodob/PycharmProjects/untitled/client.py", line 14, in listen_for_image
    while part.decode() != 'Sent':
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

编辑: 我尝试切换编码器来解决这个问题,例如:

Client.py:

def listen_for_image():
    bytes_data = socket_con.recv(1024)
    part = bytes_data
    i = 1
    print("Part #", str(i))
    while part.decode('ISO-8859-1') != 'Sent':
        part = socket_con.recv(1024)
        bytes_data += part
        i += 1
        print("Part #", str(i))
    return bytes_data

Server.py:

def send_screen_shot():
    con.send('Img'.encode())
    image = ImageGrab.grab()
    start = 0
    end = 1024
    while end < len(image.tobytes()):
        con.send(image.tobytes(encoder_name='ISO-8859-1')[start:end])
        start = end + 1
        end += 1024
    con.send("Sent".encode('ISO-8859-1'))

然后我在服务器端收到错误:

Traceback (most recent call last):
  File "C:\Python\Python35\lib\site-packages\PIL\Image.py", line 437, in _getencoder
    encoder = getattr(core, encoder_name + "_encoder")
AttributeError: module 'PIL._imaging' has no attribute 'ISO-8859-2_encoder'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:/Users/dodob/PycharmProjects/untitled/server.py", line 42, in <module>
    send_screen_shot()
  File "C:/Users/dodob/PycharmProjects/untitled/server.py", line 19, in send_screen_shot
    con.send(image.tobytes(encoder_name='ISO-8859-2')[start:end])
  File "C:\Python\Python35\lib\site-packages\PIL\Image.py", line 681, in tobytes
    e = _getencoder(self.mode, encoder_name, args)
  File "C:\Python\Python35\lib\site-packages\PIL\Image.py", line 441, in _getencoder
    raise IOError("encoder %s not available" % encoder_name)
OSError: encoder ISO-8859-2 not available

客户端一直这样运行:

...
Part # 2376824
Part # 2376825
Part # 2376826
Part # 2376827
Part # 2376828
Part # 2376829
Part # 2376830
Part # 2376831
Part # 2376832
Part # 2376833
Part # 2376834
...

我认为这个错误是因为没有这样的编码器但我尝试了多个编码器并且每次都会发生..但无论如何,我不知道为什么客户端继续运行,recv 函数应该停止直到它收到一些东西,在这里它永远运行。

感谢您的帮助。

【问题讨论】:

    标签: python python-3.x sockets


    【解决方案1】:

    随便用

    while part != b'Sent':
    

    始终保持相同的风格。您的问题是您正在尝试解码图像中的二进制数据以及文本。它不是。而且您不需要将其转换为文本来与您的已知值进行比较 - 您只需使用 bytes 作为您的已知值。

    你也想改变这个:

    while end < len(image.tobytes()):
        con.send(image.tobytes(encoder_name='ISO-8859-1')[start:end])
        start = end + 1
        end += 1024
    con.send("Sent".encode('ISO-8859-1'))
    

    到这里:

    img_bytes = image.tobytes()
    while end < len(img_bytes):
        con.send(img_bytes[start:end])
        start = end + 1
        end += 1024
    con.send("Sent".encode())
    

    这将节省您每次将图像重新转换为字节的时间。如果您的图像大小为 1024000 字节,您将调用该函数 2,000 次。不要那样做。这可能不是一个严重的问题,因为网络传输速度慢了几个数量级,但您仍然可以缩短十分之一到整秒的时间,具体取决于图像的大小。

    哦,还有一件事:

    while part and part != b'Sent':
        part = socket_con.recv(1024)
        bytes_data += part
        i += 1
        print("Part #", str(i))
    

    这样,如果套接字关闭,您实际上会退出循环。当套接字关闭时,保证.recv 将返回一个空字符串(字节)。这将评估为False,因此如果您收到没有数据,那么它将退出此循环。

    【讨论】:

    • 太好了,这部分现在可以工作了,它引发了另一个错误,但我会努力解决它!
    • Emm ,一个简单的问题 - 例如,如果字节长度是 4608,我需要将它从 0 发送到 4608,包括两者?含义0(含)- 1024、1025-2048、2049-3072、3073-4096、4097-4608(含)
    • 我对你的问题有点困惑。我认为你有足够的代表来talk in the python room
    【解决方案2】:

    如果您像这样通过套接字发送图像,您会注意到还有一些字节尚未发送。
    为了避免这种情况,请替换

    start = end + 1
    

    start = end
    

    【讨论】:

      猜你喜欢
      • 2014-07-13
      • 2013-12-31
      • 2011-04-11
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      • 2013-12-17
      相关资源
      最近更新 更多