HTTP协议中的TRANFER-ENCODING:CHUNKED编码解析

通常情况下,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发送的缓存大小。

java http data chunk_Http chunked协议相关推荐

  1. java http data chunk_HTTP协议之Chunked解析

    在网上找了好一会,始终没发现有解析Chunked编码的文章,那就自己写一个吧,呵呵.网上使用ChuPHP 在网上找了好一会,始终没发现有解析Chunked编码的文章,那就自己写一个吧,呵呵. 网上使用 ...

  2. 缓冲区溢出_在Java中使用Google的协议缓冲区

    缓冲区溢出 最近发布了有效的Java第三版,我一直对确定此类Java开发书籍的更新感兴趣,该书籍的最新版本仅通过Java 6进行了介绍. 在此版本中,显然存在与Java 7 , Java 8和Java ...

  3. java使用缓冲区读取文件_在Java中使用Google的协议缓冲区

    java使用缓冲区读取文件 最近发布了 有效的Java第三版 ,我一直对确定此类Java开发书籍的更新感兴趣,该书籍的最新版本仅通过Java 6进行了介绍 . 在此版本中,显然存在与Java 7 , ...

  4. 在Java中使用Google的协议缓冲区

    最近发布了 有效的Java第三版 ,我一直对确定此类Java开发书籍的更新感兴趣,该书籍的最新版本仅通过Java 6进行了介绍 . 在此版本中,显然有与Java 7 , Java 8和Java 9密切 ...

  5. Java实例练习——基于UDP协议的多客户端通信

    昨天学习了UDP协议通信,然后就想着做一个基于UDP的多客户端通信(一对多),但是半天没做出来,今天早上在参考了很多代码以后,修改了自己的代码,然后运行成功,在这里分享以下代码,也说一下自己的认识误区 ...

  6. c客户端http post chunked协议上传到服务器demo源码

    下面例子中 :c 客户端采用 chunked协议上传到服务器,java 服务器返回的不是chunked 协议 chunked 编码协议格式参考 https://blog.csdn.net/wy5761 ...

  7. Java 面试知识点解析——网络协议篇

    Java 面试知识点解析--网络协议篇 前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 ...

  8. java basic data type,java基本数据类型--Basic Datatypes

    Variables are nothing but reserved memory locations to store values. This means that when you create ...

  9. Java学习系列(十八)Java面向对象之基于UDP协议的网络通信

    UDP协议:无需建立虚拟链路,协议是不可靠的. A节点以DatagramSocket发送数据包,数据报携带数据,数据报上还有目的目地地址,大部分情况下,数据报可以抵达:但有些情况下,数据报可能会丢失 ...

最新文章

  1. 创建用于存放备份还原文件的网络文件夹(DPM配置管理系列七)
  2. EL与OGNL以及值栈的理解
  3. mysql多大_洞悉MySQL底层架构:游走在缓冲与磁盘之间
  4. php连接mysql原生_php链接mysql原生写法
  5. Flash/Flex学习笔记(34):AS3中的自定义事件
  6. html页面画一个矩形,使用HTML5 canvas绘制一个矩形的方法
  7. GNU make manual 翻译( 一百八十七)
  8. PMP培训班内部资料,免费分享
  9. RDP Wrapper
  10. 如何从道客巴巴上下载收费文档之我见
  11. cuda历史版本下载
  12. 家里的无线网最近总是网速不稳定,一阵一阵的卡,是怎么回事?
  13. 智能电视机顶盒开发记录
  14. UVA12307 Smallest Enclosing Rectangle 题解
  15. node.js版本不同,跑不起项目(个人笔记)
  16. 计算机网络管理工作记录,网络管理如何查看电脑开机、关机记录
  17. 阿里云 远程mysql_阿里云远程mysql
  18. 开关调色新世界BP2888电源解决方案
  19. 老罗的Android系统分析(三横三纵)
  20. 学编程的人那么多,到底编程的出路在哪?

热门文章

  1. 蒲公英 Ghost Win 7 Sp1(x86/x64)旗舰版 2018 08
  2. Switchable Normalization
  3. 诚邀大数据、云计算等方向讲师
  4. python语言数据类型与运算符课后作业_Python学习——02-Python基础——【2-运算符与基本数据类型】——课后作业...
  5. kindle推送设置
  6. 中国民航飞行学院人事薪资管理系统实践案例 1
  7. 运动打卡软件app开发功能
  8. 新浪导航栏(CSS)
  9. 模型压缩--剪枝篇(转载)
  10. 爱快软路由安装Docker插件