HTTP/2的连接建立之后,两个端点之间就可以开始交换“帧”了。
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+
帧的格式如上图所示。所有的帧都以一个9字节的帧头开始,后面跟随变长的有效载荷。
帧头的字段定义如下:
帧的有效载荷的结构和内容完全依赖于帧类型。
帧的有效载荷的大小受接收者在SETTINGS_MAX_FRAME_SIZE设置中公告的最大值限制。这个设置可以是2^14 (16,384) 和 2^24-1(16,777,215)字节之间的任意值。
所有HTTP/2的实现都必须有能力接收并且最低限度能处理多达2^14字节长度(外加9字节长度的帧头)的帧。当描述帧的大小时,帧头的大小的不包含在内的。某些帧类型,例如PING帧,对有效载荷的数据大小添加了额外的限制。
如果帧超出了SETTINGS_MAX_FRAME_SIZE定义的最大长度,或者超出帧类型定义的任何限制,或者太小而无法包含强制帧数据,端点都必须发送一个FRAME_SIZE_ERROR错误码。帧中能够修改整个连接状态的帧大小错误必须被视为一个连接错误;这包括所有携带报头块(也就是HEADERS,PUSH_PROMISE和CONTINUATION)或SETTINGS的帧,以及所有流标识符是0的帧。
端点没有义务使用帧中的全部可用空间。使用小于最大长度的帧可以提高响应性。在发送时间敏感的帧(例如,RST_STREAM,WINDOW_UPDATE或PRIORITY)时,发送大尺寸的帧会导致延迟。如果被一个大帧阻塞传输,那么会影响性能。
与HTTP1.x一样,HTTP/2的报头字段包含一个名字和一个或多个值。报头字段在HTTP请求和响应中使用,也在服务端推送操作中使用。
报头列表是0个或多个报头字段的集合。当在一个连接上传输时,利用HTTP报头压缩,报头列表被序列化为一个报头块。然后,序列化的报头块被切分为一个或多个字节序列(称为“报头块碎片”),再作为HEADERS,PUSH_PROMISE或CONTINUATION等帧的有效载荷被传输出去。
Cookie报头字段通过HTTP映射特殊处理。
接收端通过连接碎片重组报头块,然后解压缩报头块来重建报头列表。
一个完整的报头块包含:
报头压缩是有状态的。在整个连接中,使用一个压缩上下文和一个解压缩上下文。报头块中的解码错误必须被视为一个COMPRESSION_ERROR类型的连接错误。
每个报头块被作为离散单元处理。报头块必须作为连续的帧序列传输,没有任何类型或任何其它流的交错帧。在HEADERS或CONTINUATION帧序列中的最后一个帧必须设置END_HEADERS标识。在PUSH_PROMISE或CONTINUATION帧序列中的最后一个帧必须设置END_HEADERS标识。这允许一个报头块在逻辑上等价于一个独立帧。
报头块碎片只能作为HEADERS,PUSH_PROMISE或CONTINUATION帧的有效载荷,这是因为这些帧携带了能够修改接收端维护的压缩上下文的数据。接收 HEADERS,PUSH_PROMISE或CONTINUATION帧的端点需要重组报头块并执行解压缩操作,即使这些帧将被丢弃。如果接收端没有解压缩报头块,那么它必须以一个类型是COMPRESSION_ERROR的连接错误终止连接。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/jianfyun/article/details/48007209