Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 内容编码:gzip+传输编码:使用gzip/zlib进行分块会给出不正确的头检查_Python_Python 3.x_Gzip_Zlib_Transfer Encoding - Fatal编程技术网

Python 内容编码:gzip+传输编码:使用gzip/zlib进行分块会给出不正确的头检查

Python 内容编码:gzip+传输编码:使用gzip/zlib进行分块会给出不正确的头检查,python,python-3.x,gzip,zlib,transfer-encoding,Python,Python 3.x,Gzip,Zlib,Transfer Encoding,如何使用gzip编码管理分块数据? 我有一个服务器,它以以下方式发送数据: HTTP/1.1 200 OK\r\n ... Transfer-Encoding: chunked\r\n Content-Encoding: gzip\r\n \r\n 1f50\r\n\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xec}\xebr\xdb\xb8\xd2\xe0\xef\xb8\xea\xbc\x03\xa2\xcc\x17\xd9\xc7\xba\xfa\x1

如何使用gzip编码管理分块数据? 我有一个服务器,它以以下方式发送数据:

HTTP/1.1 200 OK\r\n
...
Transfer-Encoding: chunked\r\n
Content-Encoding: gzip\r\n
\r\n
1f50\r\n\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xec}\xebr\xdb\xb8\xd2\xe0\xef\xb8\xea\xbc\x03\xa2\xcc\x17\xd9\xc7\xba\xfa\x1e\xc9r*\x93\xcbL\xf6\xcc\x9c\xcc7\xf1\x9c\xf9\xb6r\xb2.H ... L\x9aFs\xe7d\xe3\xff\x01\x00\x00\xff\xff\x03\x00H\x9c\xf6\xe93\x00\x01\x00\r\n0\r\n\r\n
我有过一些不同的方法,但有些东西我忘了

data = b''
depleted = False
while not depleted:
    depleted = True
    for fd, event in poller.poll(2.0):
        depleted = False
        if event == select.EPOLLIN:
            tmp = sock.recv(8192)
            data += zlib.decompress(tmp, 15 + 32)
也尝试在obv之后解码数据\r\n\r\n: zlib.error:解压缩数据时出错-3:标头检查不正确

因此,我认为一旦数据以其完整格式接收,就应该对其进行解压缩

        ...
        if event == select.EPOLLIN:
            data += sock.recv(8192)
data = zlib.decompress(data.split(b'\r\n\r\n',1)[1], 15 + 32)
同样的错误。还尝试解压缩数据[:-7],因为数据末尾的区块ID以及数据[2:-7]和其他各种组合,但错误相同

我还通过以下方式尝试了gzip模块:

with gzip.GzipFile(fileobj=Bytes(data), 'rb') as fh:
    fh.read()
但这并不是一个gzip文件

即使将服务器接收到的数据记录到文件中,然后在端口80上创建一个服务器套接字,再次为数据提供服务,就像对浏览器一样,它也能完美地呈现数据,使数据保持完整。 我获取了这些数据,去掉了标题,没有其他内容,然后在文件上尝试了gzip:

感谢@mark adler,我生成了以下代码来取消分块数据:

unchunked = b''
pos = 0
while pos <= len(data):
    chunkLen = int(binascii.hexlify(data[pos:pos+2]), 16)
    unchunked += data[pos+2:pos+2+chunkLen]
    pos += 2+len('\r\n')+chunkLen

with gzip.GzipFile(fileobj=BytesIO(data[:-7])) as fh:
    data = fh.read()
这将产生操作错误:CRC检查失败0x70a18ee9!=0x5666e236,更近一步。简而言之,我根据以下四个部分剪辑数据:

无法在上拆分,因为压缩数据可能包含,如果足够长,肯定会包含该序列。您需要首先使用提供的长度(例如,第一个长度1f50)解块,然后将结果块送入解压。压缩数据以\x1f\x8b开头

分块是十六进制数,crlf,有那么多字节的分块,crlf,十六进制数,crlf,分块,crlf,…,最后一个长度为零的分块,[可能是一些头],crlf。

由于压缩数据可能包含,并且如果足够长,肯定会包含该序列,因此不能在\r\n上拆分。您需要首先使用提供的长度(例如,第一个长度1f50)解块,然后将结果块送入解压。压缩数据以\x1f\x8b开头


分块是十六进制数,crlf,有那么多字节的分块,crlf,十六进制数,crlf,chunk,crlf,…,最后一个零长度的分块,[可能是一些头],crlf。

@mark adler给了我一些关于HTML协议中分块模式如何工作的好建议,除此之外,我还摆弄了不同的解压数据的方法

你应该把这些块缝成一堆 你应该使用gzip而不是zlib 您只能解压整个缝合的块,分部分进行将不起作用 以下是上述三个问题的解决方案:


@MarkAdler就HTML协议中的分块模式如何工作给了我一些很好的建议,除此之外,我还尝试了不同的解压数据的方法

你应该把这些块缝成一堆 你应该使用gzip而不是zlib 您只能解压整个缝合的块,分部分进行将不起作用 以下是上述三个问题的解决方案:


1f50应该是,50字节?或因为我猜在那里的某个地方会有另一个长度标识符?它意味着1f50字节。用十六进制。最后一个区块以没有长度的\r\n结尾。这开始有帮助了:哈哈,太棒了@Torxed:我更新了分块描述以使其更完整。它仍然有点混乱,我不知道是因为有那么多字节的句子分块让我有点不舒服,还是因为你在任何字节之后继续,crlf,应该在那里停止,因为它让我对半成品伪语法感到困惑。尽管这是我自己的错:即使我写了一个完整的答案,回答了有关语法、如何处理以及使用什么库/方法来解压数据的问题,你也会赢。1f50应该是,50字节?或因为我猜在那里的某个地方会有另一个长度标识符?它意味着1f50字节。用十六进制。最后一个区块以没有长度的\r\n结尾。这开始有帮助了:哈哈,太棒了@Torxed:我更新了分块描述以使其更完整。它仍然有点混乱,我不知道是因为有那么多字节的句子分块让我有点不舒服,还是因为你在任何字节之后继续,crlf,应该在那里停止,因为它让我对半成品伪语法感到困惑。尽管这是我自己的错:即使我写了一个完整的答案,回答了有关语法、如何处理语法以及使用什么库/方法来解压数据的问题,你还是会赢的。1。你不需要把这些块缝成一堆。它可能更方便,但不是必需的。3.你可以4。如果您不理解它们,则必须忽略它们,即忽略可选。。。直到\r\n。不要在此处使用hexlify。块长度是一个十六进制数,例如intb'ff',16==255,单位为th
大小写是两个字节b'f'和b'f';ordb'f'==102==0x66,即b'f'==b'\x66'这就是为什么binascii.hexlifyb'ff'==b'6666'注意:这里是ascii b'6',即b'\x36'。您不应该使用find,因为如果传输的数据中有错误,find可能会在压缩数据中找到一个\r\n。您应该在正确的位置专门查找正确的数据。您应该查找十六进制数字。至少需要有一个。如果没有,则返回错误。寻找更多的十六进制数字。如果第一个非十六进制数字不是\r,则为错误。如果下一个字符不是\n,则返回错误。然后计算块的字节数。如果块后面的下一个字节不是\r,则返回错误。如前所述,您不需要首先组装整个流。您可以一次向解压器提供一个块,这将使用更少的内存。制作一个zlib.decompressobj对象并向其提供数据。提供等于15+16的wbits将解压gzip格式。@torx:hexlifyb'1f50'==b'31663530',intb'1f50',16==8016,请尝试Python shell中的表达式,使用它直到您理解b'1f50'!=b'\x1f\x50'和lenb'1f50'==4和lenb'\x1f\x50'==21。你不需要把这些块缝成一堆。它可能更方便,但不是必需的。3.你可以4。如果您不理解它们,则必须忽略它们,即忽略可选。。。直到\r\n。不要在此处使用hexlify。块长度是一个十六进制数,例如intb'ff',16==255,在本例中是两个字节b'f'和b'f';ordb'f'==102==0x66,即b'f'==b'\x66'这就是为什么binascii.hexlifyb'ff'==b'6666'注意:这里是ascii b'6',即b'\x36'。您不应该使用find,因为如果传输的数据中有错误,find可能会在压缩数据中找到一个\r\n。您应该在正确的位置专门查找正确的数据。您应该查找十六进制数字。至少需要有一个。如果没有,则返回错误。寻找更多的十六进制数字。如果第一个非十六进制数字不是\r,则为错误。如果下一个字符不是\n,则返回错误。然后计算块的字节数。如果块后面的下一个字节不是\r,则返回错误。如前所述,您不需要首先组装整个流。您可以一次向解压器提供一个块,这将使用更少的内存。制作一个zlib.decompressobj对象并向其提供数据。提供等于15+16的wbits将解压gzip格式。@torx:hexlifyb'1f50'==b'31663530',intb'1f50',16==8016,请尝试Python shell中的表达式,使用它直到您理解b'1f50'!=b'\x1f\x50'和lenb'1f50'==4和lenb'\x1f\x50'==2
unchunked = b''
pos = 0
while pos <= len(data):
    chunkNumLen = data.find(b'\r\n', pos)-pos
#   print('Chunk length found between:',(pos, pos+chunkNumLen))
    chunkLen=int(data[pos:pos+chunkNumLen], 16)
#   print('This is the chunk length:', chunkLen)
    if chunkLen == 0:
#       print('The length was 0, we have reached the end of all chunks')
        break
    chunk = data[pos+chunkNumLen+len('\r\n'):pos+chunkNumLen+len('\r\n')+chunkLen]
#   print('This is the chunk (Skipping',pos+chunkNumLen+len('\r\n'),', grabing',len(chunk),'bytes):', [data[pos+chunkNumLen+len('\r\n'):pos+chunkNumLen+len('\r\n')+chunkLen]],'...',[data[pos+chunkNumLen+len('\r\n')+chunkLen:pos+chunkNumLen+len('\r\n')+chunkLen+4]])
    unchunked += chunk
    pos += chunkNumLen+len('\r\n')+chunkLen+len('\r\n')

with gzip.GzipFile(fileobj=BytesIO(unchunked)) as fh:
    unzipped = fh.read()

return unzipped
def http_gzip(data):
    compressed = gzip.compress(data)

    # format(49, 'x') returns `31` which is `\x31` but without the `\x` notation.
    # basically the same as `hex(49)` but ment for these kind of things.
    return bytes(format(len(compressed), 'x')),'UTF-8') + b'\r\n' + compressed + b'\r\n0\r\n\r\n'