http的chunked transfer协议分析

在rfc文档中对chunked transfer协议进行了定义:

从rfc文档里可以看到Chunked-Body的四部分组成:

对应回具体的协议数据:

可以看到这个server response包含了很多Data chunk。上面的协议是由下面的代码产生的:

从上面的代码可以看到几件事:

  1. 数据在while循环里面,被拆开成几个chunk进行传输。
  2. 所有chunk传输完成以后,输出0\r\n作为整个chunked transfer的结束标记。
  3. 最后尾部输出了一个Checksum的trailer。

先从每一个chunk开始说起。

chunk

从上面的代码可以看到,每一个chunk先输出这个chunk的size,然后是跟着\r\n,然后是这个chunk的具体数据,然后是\r\n作为结束。

对应回实际的数据分析看一下:

可以看到一个具体的chunk,是对应代码的输出的:首先包含Chunk size,然后是data,然后是Chunk boundary

其中Chunk sizeChunk 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. 1*("0")
  2. 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的协议分析。

Powered by Jekyll and Theme by solid