Zlib不会解压缩python 2.7

时间:2018-03-25 01:39:21

标签: python compression

我正在尝试通过套接字将数据从服务器移动到客户端 我尝试从服务器压缩数据并将其发送到套接字,
但当我尝试在客户端解压缩时,我收到此错误:

zlib.error: Error -5 while decompressing data: incomplete or truncated stream

我想我知道为什么,但我不知道为什么会这样。 也许是因为我尝试解压缩"未压缩"数据, 因为如果客户端获得数据,它不知道数据是否被压缩并且现在尝试压缩它会导致错误。 也许我完全错了,但我不知道如何解决它,我需要你的帮助。

客户端:获取数据(表示图像的字符串)

def room_client(port,ip):
roomC = socket.socket()
roomC.connect((ip, port))


while True:
    print 'in while of client server'
    #recv pict
    #display
    #send ack

    img = ""
    size = roomC.recv(1024)
    roomC.sendall(size)

    while len(img) < int(size):
        data = roomC.recv(1024)
        img += data

    roomC.send("ACK")
    to_pic = img.split('@')[0]
    print to_pic
    scrn = open("monitor_serv.png", "wb")
    scrn.write(zlib.decompress(to_pic))
    scrn.close()

服务器:发送图片(截图)

def room_server(port):
#sends pictures
print 'in room_server '
roomS = socket.socket()
roomS.bind(('0.0.0.0',port))
roomS.listen(1)

client, addr = roomS.accept()




while True:
    print 'in while of room server'
    # take picture
    # send picture
    # recv ack

    flag = True
    img1 = ImageGrab.grab()
    send = zlib.compress(img1.tobytes())
    size = img1.size

    send = send + "@" + str(size[0]) + "@"+ str(size[1]) + "@0@0"
    client.sendall(str(len(send)))
    print "0"
    f = client.recv(1024)
    print "A ", f
    client.sendall(send)
    g = client.recv(1024)
    print "C ", g
    while True:
        if flag:
            flag = False
            img2 = ImageGrab.grab()
            coordinates = equal(img1, img2)
            cropped_image = img2.crop(coordinates)

        else:
            flag = True
            img1 = ImageGrab.grab()
            coordinates = equal(img1, img2)
            cropped_image = img1.crop(coordinates)

        if coordinates is not None:
            size = cropped_image.size
            send = zlib.compress(cropped_image.tobytes())
            try:
                send = send + "@" + str(size[0]) + "@" + \
                str(size[1]) + "@" + str(coordinates[0]) + "@" + str(coordinates[1])

                client.sendall(str(len(send)))
                client.recv(1024)

                client.sendall(send)
                client.recv(1024)
            except:
                break

1 个答案:

答案 0 :(得分:1)

在服务器上,您发送的是:

send = zlib.compress(img1.tobytes())
size = img1.size

send = send + "@" + str(size[0]) + "@"+ str(size[1]) + "@0@0"

在客户端上,你正在解析它:

to_pic = img.split('@')[0]
print to_pic
scrn = open("monitor_serv.png", "wb")
scrn.write(zlib.decompress(to_pic))

几乎所有的任意压缩文件都会有一个@个字节。所以你的to_pic将在第一个被截断。这意味着zlib几乎总会给你一个错误,说你已经给它一个截断的流。

您需要提出一些其他方法来构建数据。一些选择:

  • 您可以只发送data@width@height@0@0前缀为其字节长度,宽度和高度,而不是发送前缀为该字符串字节长度的data
  • 如果要将@用作分隔符,则可以转义实际图像数据中的任何@个字节,然后在另一侧转换为unescape。例如,您可以replace('@', '@@'),然后re.split在第一个@个符号上,然后replace('@@', '@')
  • 如果你rsplit拉出最后四个@而不是split来取消第一个...这有点hacky,但它会在这里工作,因为没有其他字段中可能只有@,只有压缩的图像数据字段。

协议框架还有其他问题需要重新考虑,但是当你通过localhost套接字发送小文件时,它们只会偶尔出现;这是几乎每次都会出现的唯一一个。不幸的是,这并不意味着你不需要修复其他的;它只是意味着他们将更难调试。

与此同时,你的设计还有另一个缺陷:

ImageGrab.grab()获得的内容(甚至在裁剪之前)不是PNG图像,而是原始的PIL / Pillow Image数据。您在服务器上压缩它,在客户端上解压缩它,并将这些字节保存为PNG文件。你不能这样做。

一种选择是在客户端上也使用Pillow:从解压缩的字节创建一个Image对象,然后告诉它将自己保存到PNG文件中。

另一种选择是让服务器以PNG格式导出为字节,而不是为您提供原始字节。这个版本有两个很大的优点:不需要在客户端安装PIL,并且PNG数据已经被压缩,因此您可以废弃所有zlib内容并编写更简单的代码。