通用首部字段Transfer-Encoding:chunked详解

分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。

如何判断传输完成

  • 在早期不支持持久连接的时候,其实是可以依靠连接断开来判定当前传输已经结束,大部分浏览器也是这么干的,但这并不是规范的操作。应该使用 Content-Length 这个头部,来指定当前传输的实体内容长度。
  • Content-length引入的新问题:由于 Content-Length 字段必须真实反映实体长度,但是对于动态生成的内容来说,在内容创建完之前,长度是不可知的。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。

对于定长包体

Content-Length 在这里起到了一个响应实体已经发送结束的判断依据。这样的情况下,我们就要求 Content-Length 必须和内容实体的长度一致。如果不一致,比实际短,实际上在 http 的响应体中直接被截去了。比实际长,则无法判定当前响应已经结束,会将请求持续挂起造成 Padding 状态。

对于不定长包头(或者长度无法事先知道)

  • 理想情况下,我们在响应一个请求的时候,就需要知道它的内容实体的大小。但是在实际应用中,有些时候内容实体的长度并没有那么容易获得。例如内容实体来自网络文件、或者是动态生成的。这个时候如果依然想要提前获取到内容实体的长度,只能开一个足够大的 Buffer,等内容全部缓存好了再计算。但这并不是一个好的方案,全部缓存到 Buffer 里,第一会消耗更多的内存,第二也会更耗时,让客户端等待过久。
  • 此时就需要一个新的机制,不依赖 Content-Length 的值,来判定当前内容实体是否传输完成,此时就需要 Transfer-Encoding 这个头部来判定。
  • 传输编码主要是为了解决持久连接里将数据分块传输之后,判定内容实体传输结束。

Transfer-Encoding:chunked格式

  1. 每个分块包含一个 16 进制的数据长度值和真实数据。
  2. 数据长度值独占一行,和真实数据通过 CRLF(\r\n) 分割。
  3. 数据长度值,不计算真实数据末尾的 CRLF,只计算当前传输块的数据长度。
  4. 最后通过一个数据长度值为 0 的分块,来标记当前内容实体传输结束。
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
 
25
This is the data in the first chunk
 
1C
and this is the second one
 
3
con
 
8
sequence
 
0

总结

  1. 传输编码使用 Transfer-Encoding 首部进行标记,在最新的 HTTP/1.1 协议里,它只有 chunked 这一个取值,表示分块编码。
  2. 传输编码主要是为了解决持久连接里将数据分块传输之后,判定内容实体传输结束。
  3. 分块的格式:数据长度(16进制)+ 分块数据。
  4. http 对于定长数据和不定长数据的传输方式:定长采用Content-length,不定长采用Transfer-Encoding

猜你喜欢

转载自blog.csdn.net/HZ___ZH/article/details/113375340