http://www.zeali.net/entry/129
进行Chunked编码传输的HTTP Response会在消息头部设置:
Transfer-Encoding: chunked
表示Content Body将用Chunked编码传输内容。
Chunked编码使用若干个Chunk串连而成,由一个标明长度为0的chunk标示结束。每个Chunk分为头部和正文两部分,头部内容指定下一段正文的字符总数(十六进制的数字)和数量单位(一般不写),正文部分就是指定长度的实际内容,两部分之间用回车换行(CRLF)隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些附加的Header信息(通常可以直接忽略)。具体的Chunk编码格式如下:
Chunked-Body = *chunk
"0" CRLF
footer
CRLF
chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF
hex-no-zero = <HEX excluding "0">
chunk-size = hex-no-zero *HEX
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
footer = *entity-header
RFC文档中的Chunked解码过程如下:
length := 0
read chunk-size, chunk-ext (if any) and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to entity-body
length := length + chunk-size
read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
append entity-header to existing header fields
read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding
最后提供一段PHP版本的chunked解码代码:
$chunk_size = (integer)hexdec(fgets( $socket_fd, 4096 ) );
while(!feof($socket_fd) && $chunk_size > 0) {
$bodyContent .= fread( $socket_fd, $chunk_size );
fread( $socket_fd, 2 ); // skip \r\n
$chunk_size = (integer)hexdec(fgets( $socket_fd, 4096 ) );
}
http://www.cppblog.com/hktzakar/archive/2008/11/01/26755.html
==========================================================
HTTP协议中的Tranfer-Encoding:chunked编码解析
Posted on 2007-06-21 16:49 Michael Liang 阅读(2157) 评论(2) 编辑 收藏 引用 所属分类: 学习日志
正如上篇日志所述,当不能预先确定报文体的长度时,不可能在头中包含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发送的缓存大小。
分享到:
相关推荐
有时候,Web服务器生成HTTP Response是无法在Header就确定消息大小的,这时一般来说服务器将不会提供Content-Length的头信息,而采用Chunked编码动态的提供body内容的长度。
在Boost.ASIO中处理chunked编码,你需要实现一个解析器来逐块接收和处理数据。这通常涉及读取响应头,找到“Transfer-Encoding: chunked”字段,然后循环读取每个chunk的大小和实际数据。每个chunk的大小是十六进制...
WebLogic 不兼容客户端的问题可以通过关闭 chunked 编码的传输方式或在服务端程序中添加“Content-Length”头信息来解决。开发者需要根据实际情况选择合适的解决办法,以确保系统的稳定性和可靠性。
6. **HTTP协议特性**:服务器可能使用了chunked编码(一种传输编码方式),而HttpClient可能没有正确处理。确保HttpClient版本支持chunked编码,或者服务器配置正确发送非chunked编码的响应。 7. **日志分析**:...
在HTTP协议中,`Transfer-Encoding: chunked`是一种用于分块传输编码的方式,常用于服务器无法预先知道响应体总长度的情况。这种方式将响应体分成多个块(chunks),每一块都有一个大小标识,最后以一个零长度的块...
本项目"node-chunked-response"就是一个很好的例子,展示了如何在Node.js中创建一个能够发送分块数据的HTTP服务器。 分块传输编码是HTTP/1.1协议中定义的一种机制,允许服务器在不知道响应总大小的情况下发送数据。...
2. HTTP分块编码:服务器在响应头中设置"Transfer-Encoding: chunked",然后以数据块的形式发送信息,每个块前会包含块的大小,最后发送一个0长度的块表示结束。 三、C#实现Comet 在C#中,可以使用System.Net命名...
HttpClient支持各种HTTP方法,如GET、POST、PUT、DELETE等,同时还支持HTTP/1.1协议的特性,如Keep-Alive、管道化、 chunked编码等。通过HttpClient,开发者可以方便地设置请求头、添加请求体、处理响应状态码和响应...
用ajax麻烦的地方是增加了请求数,而且需要写额外的js代码... 分块编码(chunked encoding) chunked encoding 是http1.1 才支持编码格式(当然目前没有哪个浏览器不支持1.1了),chunked encoding 与一般的响应区别如下:
- **206 Partial Content Response**: 服务器接收到范围请求后,若成功处理则返回状态码206,并在响应中加入`Content-Range`头部以指示实际发送的数据范围。 #### 三、可行性分析 针对上述提到的技术,我们可以...
服务器通过几种方式判断请求体的结束:一是客户端关闭socket连接,二是通过Content-Length字段指定数据的长度,三是不确定数据长度时使用Chunked编码,分块发送数据并在最后一块附带“0\r\n”表示结束。 HTTP/1.1...
4. ** Chunked编码**:允许服务器分块发送响应,即使不知道响应的总大小也能开始传输。 5. **Host头**:允许一个IP地址上的多台服务器托管多个域名,通过Host头指示具体请求哪个域名的资源。 HTTP协议的工作原理和...
4. **全面的HTTP/1.1支持**:完全支持HTTP/1.1协议,包括Keep-Alive、Chunked编码、Pipeline等特性。 5. **身份验证与安全**:支持多种认证机制,如Basic、Digest、NTLM等,并且可以进行SSL/TLS加密,保证数据传输的...
2. **传输编码**:支持 chunked transfer coding 和 gzip compression,这些编码方式可以处理大体积的数据传输,避免了数据大小未知时的缓冲问题,并且可以提高传输效率。 3. **HTTP方法支持**:包括GET、POST、PUT...
- **传输编码**:描述了数据如何在网络中传输,如chunked编码,适应不确定长度的数据流。 - **媒体类型**:定义了数据的类型,如text/html、image/jpeg,便于接收方根据类型解析数据。 - **产品质量值**:用于衡量...
3. **HTTP 协议支持**:HttpClient 支持 HTTP/1.0 和 HTTP/1.1 协议,以及相关的扩展,如 Keep-Alive、Pipeline 和 Chunked 编码等。 4. **Cookie 管理**:HttpClient 内置了 Cookie 管理器,可以自动处理服务器...
而现代的Comet则更加灵活,支持HTTP chunked编码,允许服务器以块的形式发送数据,而不必等待整个响应完成。 Node.js是基于V8引擎的JavaScript运行环境,以其事件驱动、非阻塞I/O的特性,成为实现Comet服务的理想...
5. **支持HTTP/1.1**:cpp-libuhttpd支持最新的HTTP/1.1协议,包括Keep-Alive连接、 Chunked编码等特性。 6. **安全特性**:虽然cpp-libuhttpd并非一个完整的Web应用框架,但可以通过配合SSL/TLS实现HTTPS,增强...
Transfer-Encoding是HTTP协议中的一种机制,用于描述消息请求(request)和响应(response)所附带的实体对象(entity)的传输形式。它的规范定义格式如下:Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-...