transfer-encoding chunked , Transfer-Encoding 的作用

本文深入解析HTTP1.1协议中的Transfer-Encoding头,阐述其在数据传输中的作用,特别是在chunked编码方式下如何解决未知长度数据的传输问题。同时对比Content-Encoding,解释两者区别及与Content-Length的关系。

通过HTTP传送数据时,有些时候并不能事先确定body的长度,因此无法得到Content-Length的值, 就不能在header中指定Content-Length了,造成的最直接的影响就是:接收方无法通过Content-Length得到报文体的长度, 那怎么判断发送方发送完毕了呢?HTTP 1.1协议在header中引入了Transfer-Encoding,当其值为chunked时, 表明采用chunked编码方式来进行报文体的传输

HTTP 1.1中有两个实体头(Entity-Header)直接与编码相关,分别为Content-Encoding和Transfer-Encoding.
先说Content-Encoding, 该头表示实体已经采用了的编码方式.Content-Encoding是请求URL对应实体(Entity)本身的一部分.比如请求URL为http://host/image.png.gz时,可能会得到的Content-Encoding为gzip.Content-Encoding的值是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity等.


与Content-Encoding头对应,HTTP请求中包含了一个Accept-Encoding头,该头用来说明用户代理(User-Agent,一般也就是浏览器)能接受哪些类型的编码. 如果HTTP请求中不存在该头,服务器可以认为用户代理能接受任何编码类型.

接下来重点描述Transfer-Encoding, 该头表示为了达到安全传输或者数据压缩等目的而对实体进行的编码. Transfer-Encoding与Content-Encoding的不同之处在于:

 

  1. Transfer-Encoding只是在传输过程中才有的,并非请求URL对应实体的本身特性.
  2. Transfer-Encoding是一个"跳到跳"头,而Content-Encoding是"端到端"头.

该头的用途举例如,请求URL为http://host/abc.txt,服务器发送数据时认为该文件可用gzip方式压缩以节省带宽,接收端看到Transfer-Encoding为gzip首先进行解码然后才能得到请求实体.
此外多个编码可能同时对同一实体使用,所以Transfer-Encoding头中编码顺序相当重要,它代表了解码的顺序过程.同样,Transfer-Encoding的值也是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity/chunked等.
Transfer-Encoding中有一类特定编码:chunked编码.该编码将实体分块传送并逐块标明长度,直到长度为0块表示传输结束, 这在实体长度未知时特别有用(比如由数据库动态产生的数据). HTTP1.1标准规定,只要使用了Transfer-Encoding的地方就必须使用chunked编码,并且chunked必须为最后一层编码.任何HTTP 1.1应用都必须能处理chunked编码.
与Transfer-Encoding对应的请求头为TE,它主要表示请求发起者愿意接收的Transfer-Encoding类型. 如果TE为空或者不存在,则表示唯一能接受的类型为chunked.
其他与Transfer-Encoding相关的头还包括Trailer,它与chunked编码相关,就不细述了.

顾名思义,Content-Length表示传输的实体长度,以字节为单位(在请求方法为HEAD时表示会要发送的长度,但并不实际发送.).Content-Length受Transfer-Encoding影响很大,只要Transfer-Encoding不为identity,则实际传输长度由编码中的chunked决定,Content-Length即使存在也被忽略.

关于HTTP Message Body的长度
在HTTP中有消息体(Message body)和实体(Entity body)之分,简单说来在没有Transfer-Encoding作用时,消息体就是实体,而应用了Transfer-Encoding后,消息体就是编码后的实体,如下:

    Message body = Transfer-Encoding encode(Entity body)
如何确定消息体的长度? HTTP 1.1标准给出了如下方法(按照优先级依次排列):
    1, 响应状态(Response Status)为1xx/204/304或者请求方法为HEAD时,消息体长度为0.
    2, 如果使用了非"identity"的Transfer-Encoding编码方式,则消息体长度由"chunked"编码决定,除非该消息以连接关闭为结束.
    3, 如果存在"Content-Length"实体头,则消息长度为该数值.
    3, 如果消息使用关闭连接方式代表消息体结束,则长度由关闭前收到的长度决定. 该条对HTTP Request包含的消息体不适用.


 

<think>嗯,用户想了解Transfer-Encoding chunked的定义和用法。让我先回忆一下相关知识。根据引用[2],Transfer-Encoding: chunkedHTTP/1.1中的分块传输编码方式,用于在不知道内容长度时逐步传输数据。每个分块包含16进制长度值和数据,最后以长度为0的分块结束。 用户可能想知道为什么需要这个机制,对吧?引用[3]提到,当服务器无法预先知道内容大小时,比如动态生成的内容,用Content-Length就不现实,这时候用分块传输。这样服务器可以一边生成数据一边发送,而不必等待全部内容准备好。 还有,用户可能关心分块的具体格式。引用[2]中的示例显示,每个块先发送长度,然后是数据,最后是CRLF。比如25表示第一块有37字节的数据。这样客户端可以逐步接收和解析数据,提高响应速度。 另外,分块传输的应用场景是什么?引用[4]提到,浏览器收到一个块后就可以开始解析页面,同时继续下载其他资源,如JS、CSS等。这对性能优化有帮助,尤其是对于大页面或慢速网络的情况。 用户可能还会想知道分块传输与Content-Encoding的区别。引用[1]指出Transfer-Encoding是对传输过程的编码,而Content-Encoding是内容本身的编码,比如gzip压缩。两者可以同时使用,比如先压缩再分块传输。 需要确认是否涵盖了定义、工作原理、格式和应用场景。可能还需要提到分块传输的优点,比如减少延迟,支持流式传输。最后,相关问题可以引导用户进一步了解细节或比较其他传输方式。</think>### Transfer-Encoding: chunked 的定义及用法 #### 1. **定义** **Transfer-Encoding: chunked** 是 HTTP/1.1 协议中定义的一种分块传输编码方式,用于在服务器无法预先确定响应内容长度时,将数据分割为多个分块(chunk)逐步传输[^2][^3]。每个分块包含一个十六进制的数据长度值和实际数据,最终通过一个长度为 `0` 的分块标记传输结束[^2]。 --- #### 2. **工作原理** - **分块格式**: 每个分块由以下部分组成: $$ \text{数据长度(16进制)} + \text{CRLF} + \text{实际数据} + \text{CRLF} $$ 例如: ``` 25\r\n <- 数据长度(37字节) This is the data in the first chunk\r\n 1C\r\n <- 数据长度(28字节) and this is the second one\r\n 0\r\n <- 传输结束标记 ``` - **结束条件**: 当客户端接收到长度为 `0` 的分块时,表示当前响应实体传输完成[^2][^4]。 --- #### 3. **核心用途** - **动态内容传输**: 当服务器无法预先计算内容长度(如动态生成的页面、实时数据流),通过分块编码逐步传输数据,避免因等待完整内容而延迟响应[^3][^4]。 - **持久连接支持**: 在长连接(Keep-Alive)中,分块编码帮助客户端明确判断响应边界,避免因缺少 `Content-Length` 导致连接挂起[^2][^3]。 --- #### 4. **与 Content-Length 的对比** | **特性** | **Transfer-Encoding: chunked** | **Content-Length** | |------------------------|---------------------------------------|------------------------------| | 适用场景 | 动态内容、流式数据 | 静态内容(已知固定长度) | | 是否需要预知数据长度 | 不需要 | 需要 | | 传输效率 | 支持边生成边传输,减少延迟 | 需等待完整数据生成后传输 | --- #### 5. **实际应用示例** - **服务器端实现**: 通过手动刷新缓冲区(如 Python 的 `sys.stdout.flush()` 或 PHP 的 `ob_flush()`)逐块发送数据[^4]。 - **浏览器行为**: 浏览器收到首个分块后即可开始解析页面,并并行加载页面内的资源(如 JS、CSS)[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值