HTTP协议中的Tranfer-Encoding:chunked编码解析
发布日期:2021-06-30 19:27:12
浏览次数:2
分类:技术文章
本文共 2727 字,大约阅读时间需要 9 分钟。
当不能预先确定报文体的长度时,不可能在头中包含Content-Length域来指明报文体长度,此时就需要通过Transfer-Encoding域来确定报文体长度。 通常情况下,Transfer-Encoding域的值应当为chunked,表明采用chunked编码方式来进行报文体的传输。chunked编码是HTTP/1.1 RFC里定义的一种编码方式,因此所有的HTTP/1.1应用都应当支持此方式。 chunked编码的基本方法是将大块数据分解成多块小数据,每块都可以自指定长度,其具体格式如下(BNF文法): Chunked-Body = *chunk //0至多个chunk last-chunk //最后一个chunk trailer //尾部 CRLF //结束标记符 chunk = chunk-size [ chunk-extension ] CRLF chunk-data CRLF chunk-size = 1*HEX last-chunk = 1*("0") [ chunk-extension ] CRLF chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) chunk-ext-name = token chunk-ext-val = token | quoted-string chunk-data = chunk-size(OCTET) trailer = *(entity-header CRLF) 解释: Chunked-Body表示经过chunked编码后的报文体。报文体可以分为chunk, last-chunk,trailer和结束符四部分。chunk的数量在报文体中最少可以为0,无上限;每个chunk的长度是自指定的,即,起始的数据必然是16进制数字的字符串,代表后面chunk-data的长度(字节数)。这个16进制的字符串第一个字符如果是“0”,则表示chunk- size为0,该chunk为last-chunk,无chunk-data部分。可选的chunk-extension由通信双方自行确定,如果接收者不理解它的意义,可以忽略。 trailer是附加的在尾部的额外头域,通常包含一些元数据(metadata, meta means "about information"),这些头域可以在解码后附加在现有头域之后。 实例分析: 下面分析用ethereal抓包使用Firefox与某网站通信的结果(从头域结束符后开始): Address 0.......................... f 000c0 31 000d0 66 66 63 0d 0a ............... // ASCII码:1ffc"r"n, chunk-data数据起始地址为000d5 很明显,“1ffc”为第一个chunk的chunk-size,转换为int为8188.由于1ffc后马上就是 CRLF,因此没有chunk-extension.chunk-data的起始地址为000d5, 计算可知下一块chunk的起始 地址为000d5+1ffc + 2=020d3,如下: 020d0 .. 0d 0a 31 66 66 63 0d 0a .... // ASCII码:"r"n1ffc"r"n 前一个0d0a是上一个chunk的结束标记符,后一个0d0a则是chunk-size和chunk-data的分隔符。 此块chunk的长度同样为8188, 依次类推,直到最后一块 100e0 0d 0a 31 100f0 65 61 39 0d 0a...... //ASII码:"r"n"1ea9"r"n 此块长度为0x1ea9 = 7849, 下一块起始为100f5 + 1ea9 + 2 = 11fa0,如下: 100a0 30 0d 0a 0d 0a //ASCII码:0"r"n"r"n “0”说明当前chunk为last-chunk, 第一个0d 0a为chunk结束符。第二个0d0a说明没有trailer部分,整个Chunk-body结束。 解码流程: 对chunked编码进行解码的目的是将分块的chunk-data整合恢复成一块作为报文体,同时记录此块体的长度。 RFC2616中附带的解码流程如下:(伪代码) length := 0 //长度计数器置0 read chunk-size, chunk-extension (if any) and CRLF //读取chunk-size, chunk-extension //和CRLF while(chunk-size > 0 ) { //表明不是last-chunk read chunk-data and CRLF //读chunk-size大小的chunk-data,skip CRLF append chunk-data to entity-body //将此块chunk-data追加到entity-body后 read chunk-size and CRLF //读取新chunk的chunk-size 和 CRLF } read entity-header //entity-header的格式为name:valueCRLF,如果为空即只有CRLF while (entity-header not empty) //即,不是只有CRLF的空行 { append entity-header to existing header fields read entity-header } Content-Length:=length //将整个解码流程结束后计算得到的新报文体length //作为Content-Length域的值写入报文中 Remove "chunked" from Transfer-Encoding //同时从Transfer-Encoding中域值去除chunked这个标记 length最后的值实际为所有chunk的chunk-size之和,在上面的抓包实例中,一共有八块chunk-size为0x1ffc(8188)的chunk,剩下一块为0x1ea9(7849),加起来一共73353字节。 注:对于上面例子中前几个chunk的大小都是8188,可能是因为:"1ffc" 4字节,""r"n"2字节,加上块尾一个""r"n"2字节一共8字节,因此一个chunk整体为8196,正好可能是发送端一次TCP发送的缓存大小。转载地址:https://linuxstyle.blog.csdn.net/article/details/6882110 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
不错!
[***.144.177.141]2024年04月24日 09时12分36秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
SaltStack
2019-04-30
Packer 如何将 JSON 的配置升级为 HCL2
2019-04-30
Ubuntu 安装 NTP 服务
2019-04-30
NeoFetch - Linux 使用命令行查看系统信息
2019-04-30
Jenkins 控制台输出中的奇怪字符
2019-04-30
Linux添加系统调用
2019-04-30
ubuntu 18 CTF 环境搭建
2019-04-30
linux内存的寻址方式
2019-04-30
[off by null + tcache dup]lctf_easy_heap
2019-04-30
[pie+libc]national2021_pwny
2019-04-30
task_struct 结构分析
2019-04-30
ubunut16.04的pip3出现问题,重新安装pip3
2019-04-30
how2heap-double free
2019-04-30
how2heap-fastbin_dup_consolidate
2019-04-30
orw_shellcode_模板
2019-04-30
[fmt+shellcode]string
2019-04-30
fmt在bss段(neepusec_easy_format)
2019-04-30
[double free] 9447 CTF : Search Engine
2019-04-30