HTTP/2定义了多种帧的类型,每种类型都有一个唯一的8字节类型编码。在整个TCP连接或者是各个独立的流的建立和管理过程中,每种类型的帧都为特定的目的而服务。
DATA帧
DATA帧(数据帧,类型是0x0)传输与流相关联的任意的、可变长度的字节序列。例如,使用一个或多个DATA帧携带HTTP的请求和响应的有效载荷。
DATA帧可以包含填充字节序列。填充可以被添加到DATA帧,以掩盖消息的大小。因此,填充属于安全特性。
DATA帧的格式如下:
+---------------+
|Pad Length? (8)|
+---------------+-----------------------------------------------+
| Data (*) ...
+---------------------------------------------------------------+
| Padding (*) ...
+---------------------------------------------------------------+
各个字段解释如下:
- Pad Length(填充长度):8比特字段,表示填充字节序列(即上图中的Padding)的字节长度。这个字段是可选的,只有在设置了PADDED标志位时才有。
- Data(数据):具体应用数据,即帧的有效载荷减去其它字段的长度(其它字段是可选的)。
- Padding(填充字节):填充字节不包含任何应用语义值。发送时必须将填充字节的值都设置为0。接收方没有义务验证填充序列,但是可以将非0的填充字节视为类型为PROTOCOL_ERROR的连接错误。
DATA帧定义了以下标志位:
- END_STREAM (0x1):设置此标志位时表明当前帧是端点在流上发送的最后一个帧,从而导致流进入“半关闭”或“关闭”状态。
- PADDED (0x8):设置此标志位表明帧中包含“填充长度”和“填充字节”这2个字段。
DATA帧必须与一个流关联起来。如果接收到的DATA帧的流标志位是0x0,那么接收方必须响应一个类型是PROTOCOL_ERROR的连接错误。
DATA帧受流量控制支配。只有当流处于“打开”或“半关闭(远程)”状态时,才能发送DATA帧。整个DATA帧都包含在流量控制中,数据、填充长度和填充字节字段都不例外。如果接收到的DATA帧关联的流不是“打开”或“半关闭(本地)”状态,那么,接收方必须响应一个类型是STREAM_CLOSED的流错误。
“填充字节”的总数由“填充长度”字段决定。如果填充字节序列的长度等于或大于整个帧的有效载荷,那么,接收方必须将其视为一个类型是PROTOCOL_ERROR的连接错误。
一个特殊情况是,可以通过将“填充长度”字节的值设置为0,为DATA帧增加一个字节的长度。
HEADERS帧
HEADERS帧(报头帧,类型是0x1)用于打开一个流,另外可以携带一个报头块碎片。HEADERS帧可以在状态为“空闲”、“保留(本地)”、“打开”、“半关闭(远程)”的流上发送。
HEADERS帧的格式如下:
+---------------+
|Pad Length? (8)|
+-+-------------+-----------------------------------------------+
|E| Stream Dependency? (31) |
+-+-------------+-----------------------------------------------+
| Weight? (8) |
+-+-------------+-----------------------------------------------+
| Header Block Fragment (*) ...
+---------------------------------------------------------------+
| Padding (*) ...
+---------------------------------------------------------------+
各个字段的解释如下:
- Pad Length(填充长度):8比特位字段,表示填充字节序列(即上图中的Padding)的字节长度。这个字段是可选的,只有在设置了PADDED标志位时才有。
- E(排他标志位):1比特位字段,表明流依赖是排他的。这个字段是可选的,只有在设置了PRIORITY标志位时才有。
- Stream Dependency(流依赖):31比特位的流标志位,表示当前流依赖的那个流,即当前流的“父亲流”。这个字段是可选的,只有在设置了PRIORITY标志位时才有。
- Weight(权重):8比特位的整数,表示流的优先级权重,范围是1-256之间。这个字段是可选的,只有在设置了PRIORITY标志位时才有。
- Header Block Fragment(报头块碎片):报头块的片段。
- Padding(填充字节):填充字节。
HEADERS帧定义了以下标志位:
- END_STREAM(0x1):设置此标志位时表明当前帧是端点在流上发送的最后一个帧。携带END_STREAM标志位的HEADERS帧预示流的结束。然而,在相同的流中,携带END_STREAM标志位的HEADERS帧后面可以跟随一个或多个CONTINUATION帧。逻辑上,CONTINUATION帧是HEADERS帧的一部分。
- PADDED (0x8):设置此标志位时表明帧中包含“填充长度”和“填充字节”字段。
- PRIORITY(0x20):设置此字段时表明帧中包含“排他标志位”、“流依赖”和“权重”字段。
HEADERS帧的有效载荷包含一个报头块碎片。如果HEADERS帧中装不下报头块碎片,那么报头块碎片的剩余部分将被装到后面的CONTINUATION帧中。
HEADERS帧必须与一个流关联起来。如果接收到的HEADERS帧的流标志位是0x0,那么接收方必须响应一个类型是PROTOCOL_ERROR的连接错误。
HEADERS帧会改变流的状态。(参考(四) HTTP/2的流状态)
HEADERS帧可以包含填充字节。填充字段和标志位与DATA帧的相同。填充字节的长度超过为报头块碎片保留的大小时,将导致一个类型是PROTOCOL_ERROR的连接错误。