在前面两篇文章中,这里介绍了gzip压缩的一些知识点,本文将对网络传输中的传输编码做一下简单的介绍。
通过阅读本文将了解到以下几个方面:
- 什么是chunked传输编码
- 为什么要有分块传输
- 分块传输的格式
- 还原chunked编码内容
什么是chunked传输编码
前面介绍了url,base64,gzip等编码,例如URL以及base64作用是解决特殊字符传输和显示的问题,gzip目的是减少文件的大小,节约空间,提高存储传输效率。本文所介绍的chunked编码被称之为传输编码是为了解决HTTP的请求和响应过程中,响应数据分成若干个块进行传输问题。提到分块很容易联想到IP的分片,IP分片解决的是下层传输数据大小的限制,需要对上层的数据切分成片传输的问题。HTTP的分块传输的解决的是应用层动态生成数据能够及时的传输而分步骤传输的问题。在RFC2616中,见这里,如图1:
图1
为什么要有分块传输
不分块传输的场景如下图2所示
图2
分块传输的场景如下图3所示:
图3
从图2可以看到为了告诉客户端HTTP层的数据是否传输完毕,必须使用Content-Length进行说明。当客户端收到Content-Length大小的数据之后才会认为本次的HTTP请求响应结束。
但是Content-Length的值需要服务器提前计算得到。在网络发展早期,网络中传输的是文本,图片等静态的内容为主,能够提前得到传输内容的大小。但是在当前的网络中,很多的请求数据是动态生成的,如果等到数据全部生成再发送会在传输中造成较大的延迟。因此对于动态生成的数据通常是边生成边发送。在HTTP协议层面,为了支持这样的场景,就引入了HTTP分块传输的概念,如上图3所示。由于是动态传输数据,服务器无法知道传输内容大小,因此在HTTP响应的头部是没有Content-Length字段的。
分块传输的格式
关于分块传输的格式,在上述的图1中已经有所说明。值得说明的是RFC2616是早期HTTP协议的规范说明,对于最新的HTTP1.1的说明,也可查看RFC7230,见这里。
结合图1中的规范定义,以及图3中的的一个具体的应用示例。可以看到分块主要由每个块的内容,最后一个块内容,以及最后的换行构成。例如图3中第一个块的大小为31,36连个16进制,对应的是0x16,即22个字节,表示该块的大小为22个字节,向后偏移22个字节即是下一个块。最后一个块的size为30对应的是0个字节。
对于图1中trailer这个可选字段很多的实现中是不使用的。当然你可能会注意到chunk编码使用CRLF 来区分不同的块,在默写情况下可能会导致一些问题的,例如传输的数据内容符合这样的格式,幸运的是还有chunk_size来决定每个块的大小,保证歧义的问题不会发生。
还原chunked编码内容
在了解了分块传输的,原理,相信还原对应的块应该很容易,以下是还原块编码的python函数程序:
payload_ressemble = b""
while payload_raw:
length, _, chunk_body = payload_raw.partition(b"\r\n")
try:
length = int(length, 16)
except ValueError:
break
else:
if chunk_body[length:length + 2] != b"\r\n":
break
payload_raw = chunk_body[length + 2:]
payload_ressemble += chunk_body[:length]
基本的原理就是按照\r\n进行块的划分,然后按照长度偏移取每一个块的长度。
通常来说我们往往需要将pcap中的分块传输进行还原,我在后续的文章中会持续的介绍,请关注我的专栏《Pcap网络数据包处理方法大全》,具体的程序见这里。
本文为优快云村中少年原创文章,未经允许不得转载,博主链接这里。