HTTP的传输编码(Transfer-Encoding:chunked)
转载自HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP,本来是将这篇文章收藏在我的有道云笔记的,但是今天复习的时候看着这个标题这尴尬,这里转载一下…...
什么是传输编码?
传输编码在 HTTP 的报文头中,使用 Transfer-Encoding 首部进行标记,它就是指明当前使用的传输编码。
Transfer-Encoding 会改变报文的格式和传输的方式,使用它不但不会减少内容传输的大小,甚至还有可能会使传输变大,看似是一个不环保的做法,但是其实是为了解决一些特殊问题。
简单来说,传输编码必须配合持久连接去使用,为了在一个持久连接中,将数据分块传输,并标记传输结束而设计的,后面会详细讲解。
在早年间的设计里,和内容编码使用 Accept-Encoding 来标记客户端接收的压缩编码类型一样,传输编码还需要配合 TE 这个请求报文头来使用,用于指定支持的传输编码。但是在最新的 HTTP/1.1 协议规范中,只定义了一种传输编码:分块编码(chunked),所以并不需要再依赖 TE 这个头部。
这些细节,后面都会讲到。既然传输编码和持久连接是息息相关的,那我们就先来了解一下什么是持久连接。
持久连接(Persistent Connection)
持久连接通俗来讲,就是长连接,英文叫 Persistent Connection,其实按字面意思理解就好了。
在早期的 HTTP 协议中,传输数据的顺序大致分为发起请求、建立连接、传输数据、关闭连接等步骤,而持久连接,就是去掉关闭连接这个步骤,让客户端和服务端可以继续通过此次连接传输内容。
这其实也是为了提高传输效率,我们知道 HTTP 协议是建立在 TCP 协议之上的,自然有 TCP 一样的三次握手、慢启动等特性,这样每一次连接其实都是一次宝贵的资源。为了尽可能的提高 HTTP 的性能,使用持久连接就显得很重要了。为此在 HTTP 协议中,就引入了相关的机制。
在早期的 HTTP/1.0 协议中并没有持久连接,持久连接的概念是在后期才引入的,当时是通过 Connection:Keep-Alive 这个头部来标记实现,用于通知客户端或服务端相对的另一端,在发送完数据之后,不要断开 TCP 连接,之后还需要再次使用。
而在 HTTP/1.1 协议中,发现持久连接的重要性了,它规定所有的连接必须都是持久的,除非显式的在报文头里,通过 Connection:close 这个首部,指定在传输结束之后会关闭此连接。
实际上在 HTTP/1.1 中Connect 这个头部已经没有 Keep-Alive 这个取值了,由于历史原因,很多客户端和服务端,依然保留了这个报文头。
长连接带来了另外一个问题,如何判定当前数据发送完成。
判断传输完成
在早期不支持持久连接的时候,其实是可以依靠连接断开来判定当前传输已经结束,大部分浏览器也是这么干的,但这并不是规范的操作。应该使用 Content-Length 这个头部,来指定当前传输的实体内容长度。
下面举个例子,在保持持久连接的情况下,依赖 Content-Length 来确定数据发送完毕。
Content-Length 在这里起到了一个响应实体已经发送结束的判断依据。这样的情况下,我们就要求 Content-Length 必须和内容实体的长度一致,如果不一致,就会出现各种问题。
如上图所示,如果 Content-Length 小于内容实体的长度,则会截断,反之则无法判定当前响应已经结束,会将请求持续挂起造成 Padding 状态。
理想情况下,我们在响应一个请求的时候,就需要知道它的内容实体的大小。但是在实际应用中,有些时候内容实体的长度并没有那么容易获得。例如内容实体来自网络文件、或者是动态生成的。这个时候如果依然想要提前获取到内容实体的长度,只能开一个足够大的 Buffer,等内容全部缓存好了再计算。
但这并不是一个好的方案,全部缓存到 Buffer 里,第一会消耗更多的内存,第二也会更耗时,让客户端等待过久。
此时就需要一个新的机制,不依赖 Content-Length 的值,来判定当前内容实体是否传输完成,此时就需要 Transfer-Encoding 这个头部来判定。
Transfer-Encoding:chunked
前面也提到,Transfer-Encoding 在最新的 HTTP/1.1 协议里,就只有 chunked 这个参数,标识当前为分块编码传输。
分块编码传输既然只有一个可选的参数,我们就只需要指定它为 Transfer-Encoding:chunked ,后续我们就可以将内容实体包装一个个块进行传输。
分块传输的规则:
1. 每个分块包含一个 16 进制的数据长度值和真实数据。
2. 数据长度值独占一行,和真实数据通过 CRLF(\r\n) 分割。
3. 数据长度值,不计算真实数据末尾的 CRLF,只计算当前传输块的数据长度。
4. 最后通过一个数据长度值为 0 的分块,来标记当前内容实体传输结束。
在这个例子中,首先在响应头部里标记了 Transfer-Encoding: chunked,后续先传递了第一个分块 “0123456780”,长度为 b(11 的十六进制),之后分别传输了 “Hello CxmyDev” 和 “123”,最后以一个长度为 0 的分块标记当前响应结束。
chunked 的拖挂
当我们使用 chunked 进行分块编码传输的时候,传输结束之后,还有机会在分块报文的末尾,再追加一段数据,此数据称为拖挂(Trailer)。
拖挂的数据,可以是服务端在末尾需要传递的数据,客户端其实是可以忽略并丢弃拖挂的内容的,这就需要双方协商好传输的内容了。
在拖挂中可以包含附带的首部字段,除了 Transfer-Encoding、Trailer 以及 Content-Length 首部之外,其他 HTTP 首部都可以作为拖挂发送。
一般我们会使用拖挂来传递一些在响应报文开始的时候,无法确定的某些值,例如:Content-MD5 首部就是一个常见的在拖挂中追加发送的首部。和长度一样,对于需要分块编码传输的内容实体,在开始响应的时候,我们也很难算出它的 MD5 值。
注意这里在头部增加了 Trailder,用以指定末尾还会传递一个 Content-MD5 的拖挂首部,如果有多个拖挂的数据,可以使用逗号进行分割。
内容编码和传输编码结合
内容编码和传输编码一般都是配合使用的。我们会先使用内容编码,将内容实体进行压缩,然后再通过传输编码分块发送出去。客户端接收到分块的数据,再将数据进行重新整合,还原成最初的数据。
传输编码小结
我们对传输编码应该有一定的了解了。这里简单总结一下:
1. 传输编码使用 Transfer-Encoding 首部进行标记,在最新的 HTTP/1.1 协议里,它只有 chunked 这一个取值,表示分块编码。
2. 传输编码主要是为了解决持久连接里将数据分块传输之后,判定内容实体传输结束。
3. 分块的格式:数据长度(16进制)+ 分块数据。
4. 如果还有额外的数据,可以在结束之后,使用 Trailer 进行拖挂传输额外的数据。
5. 传输编码通常会配合内容编码一起使用。
此外,传输编码应该是所有 HTTP/1.1 的标准实现,应该都有支持,如果收到无法理解的经过传输编码的报文,应该直接返回 501 Unimplemented 这个状态码来回复即可。
HTTP的传输编码(Transfer-Encoding:chunked)的更多相关文章
- 网络标准之:IANA定义的传输编码
目录 简介 IANA的传输编码方式 7bit 8bit binary quoted-printable base64 总结 简介 不同的系统或者协议可以接受的数据类型是不同的,如果要在那些不支持现有数 ...
- C# 字符编码类Encoding
在网络通信中,很多情况下都是将字符信息转成字节序列进行传输.将字符序列转为字节序列的过程称为编码.当这些字节传送到接收方,接收方需要逆向将字节序列转为字符序列.这个过程就是解码. 常见编码有ASCII ...
- HTTP 协议中的 Content-Encoding 和 Transfer-Encoding(内容编码和传输编码)
转自:http://network.51cto.com/art/201509/491335.htm Transfer-Encoding,是一个 HTTP 头部字段,字面意思是「传输编码」.实际上,HT ...
- HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
题图:by @Olga Hi,大家好,我是承香墨影! HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Header)和实体组成.大多数 HT ...
- WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(下篇)
原文:WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(下篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话 ...
- rest-assured的根路径(root path)和URL编码(URL Encoding)
一.根路径(Root path) 为了避免在body方法中使用重复的路径来断言,我们可以指定一个根路径(root path),比如: 我们以前的写法是: when(). get("/some ...
- HTTP的传输编码(Transfer-Encoding:chunked) / net::ERR_INVALID_CHUNKED_ENCODING
https://blog.csdn.net/m0_37668842/article/details/89138733 https://www.cnblogs.com/jamesvoid/p/11297 ...
- HTTP协议之chunk编码(分块传输编码
Transfer-Encoding: chunked 表示输出的内容长度不能确定,普通的静态页面.图片之类的基本上都用不到这个. 但动态页面就有可能会用到,但我也注意到大部分asp,php,asp.n ...
- 字符集与字符编码 (charset & encoding)
乱码是个大坑,相信每个人都遇过,而且是个绕不过去的坑.我理解每个程序员都应该写一篇编码相关的博文,梳理自己对这一块的理解,下面是我反复理解多次之后的学习小结. 1.从记事本的不同编码说起: 打开记事本 ...
随机推荐
- Elasticsearch搜索调优
最近把搜索后端从AWS cloudsearch迁到了AWS ES和自建ES集群.测试发现search latency高于之前的benchmark,可见模拟数据远不如真实数据来的实在.这次在产线的bac ...
- ELK学习实验003:Elasticsearch 集群安装
前面已经介绍了Elasticsearch这个工具,并对单机安装做了简单介绍,现在使用三台机器做一个elasticsearch集群 一 环境准备 1.1 机器准备 1.2 同步时间 [root@node ...
- Google被墙怎么办?
Google被墙怎么办? 1 声明 请小伙伴们遵守法律法规,我们只是为了更好的查询学习资料. 想使用Google查询相关资料 想使用Google账号管理收藏夹 想使用Google商店安装软件 == 2 ...
- Java程序运行原理
概念介绍: C语言
常言道"小赌怡情".这是一个很简单的小游戏:首先由计算机给出第一个整数:然后玩家下注赌第二个整数将会比第一个数大还是小:玩家下注 t 个筹码后,计算机给出第二个数.若玩家猜对了,则 ...
- MATLAB实例:PCA(主成成分分析)详解
MATLAB实例:PCA(主成成分分析)详解 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 1. 主成成分分析 2. MATLAB解释 详细信息请看: ...
- Mac重装操作系统系统
恢复出厂设置 第一种 1.开机 2.commond + R,进入recover模式. 3.选择磁盘工具 4.显示所有设备 5.抹掉硬盘.格式选择 (1):Mac OS 扩展(日志式). (2): Ma ...
- 《图解机器学习-杉山将著》读书笔记---CH5
CH5 稀疏学习 重点提炼 提出稀疏学习的缘故: 虽然带有约束条件的最小二乘学习法结合交叉验证法,在实际应用中是非常有效的回归方法,但是,当参数特别多时,计算参数以及预测值需要大量时间.此时,我们要解 ...
- PS/2的相关知识
PS/2接口 很多微机上采用PS/2口来连接鼠标和键盘.PS/2接口与传统的键盘接口除了在接口外型.引脚有不同外,在数据传送格式上是相同的.现在很多主板用PS/2接口插座连接键盘,传统接口的键盘可以通 ...
- Android Studio build不显示Generate signed apk问题
如果是刚装的AS,那么新建一个项目,进入项目后,会发现build选项卡缺了一些选项,同时底部sync在转圈圈,其实是AS在自动下载gradle,也许还在下载build-tools,我等了11分钟才结束 ...