http的chunked transfer协议分析
在rfc文档中对chunked transfer协议进行了定义:
从rfc文档里可以看到Chunked-Body
的四部分组成:
*chunk
last-chunk
trailer
CRLF
对应回具体的协议数据:
可以看到这个server response包含了很多Data chunk
。上面的协议是由下面的代码产生的:
从上面的代码可以看到几件事:
- 数据在
while
循环里面,被拆开成几个chunk进行传输。 - 所有chunk传输完成以后,输出
0\r\n
作为整个chunked transfer的结束标记。 - 最后尾部输出了一个
Checksum
的trailer。
先从每一个chunk
开始说起。
chunk
从上面的代码可以看到,每一个chunk先输出这个chunk的size
,然后是跟着\r\n
,然后是这个chunk的具体数据,然后是\r\n
作为结束。
对应回实际的数据分析看一下:
可以看到一个具体的chunk,是对应代码的输出的:首先包含Chunk size
,然后是data
,然后是Chunk boundary
。
其中Chunk size
和Chunk boundary
都是使用0d0a
作为结束标记,其实就是\r\n
的ascii code。可以使用bash命令验证这点:
$ echo -n "\r\n" | od -x
0000000 0a0d
0000002
$
如上,可以看到\r\n
对应的ascii code就是0d0a
,因为od
命令输出的是little-endian顺序,所以是反着的。
把上面的chunk对应到rfc文档里面的描述:
可以看到实际的数据对应chunk
的标准描述,其中标准文档里的CRLF
就是\r\n
。
接下来看rfc文档关于last-chunk
的部分。
last-chunk
可以看到last-chunk
主要包含两部分:
1*("0")
CRLF
其中第一部分就是指「一个或多个零」,第二部分是CRLF
,也就是\r\n
。对应到实际的数据来看:
可以看到End of chunked encoding
这部分的值是30 0d 0a
,就是ascii code的0
,外加\r\n
。
其中0d 0a
我们已经知道对应\r\n
,那30
是怎么验证为ascii code的0
呢?可以使用bash
命令来验证:
$ echo -n "0" | od -x
0000000 0030
0000001
$
可以看到16进制的0x30
就是ascii code的0
。
分析完这部分数据,最后的数据就是trailer-part
。
trailer-part
首先还是看下rfc文档对trailer-part的定义:
翻译过来,就是加上header里面请求的entity-header
,然后用\r\n
结束。
对应到具体的数据看一下:
可以看到服务端给的trailer-part是checksum
信息,然后用0d0a
,也就是\r\n
结束。
此外,rfc
文档的要求是,header里请求trailer,才给trailer-part:
所以代码里面在请求里设置了TE
的header:
对应到请求数据如下:
以上就是对http协议中chunked transfer的协议分析。