HTTP2帧基础知识以及Header、CONTINUATION、DATA帧相关资料:

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

HTTP2帧基础知识以及Header、CONTINUATION、DATA帧相关
资料:
在HTTP2 的⽹络通讯中, Frame 是通讯中的最⼩传输单位,⾄少含有⼀个 Frame header,能够表⽰它属于哪⼀个 Stream。

⼀个具体的请求类似如下:
HTTP/2 帧通⽤格式:
帧头+负载的⽐特位通⽤结构:
帧头为固定的9个字节((24+8+8+1+31)/8=9)呈现,变化的为帧的负载(Frame Payload),负载内容是由帧类型(Type)定义。

帧长度Length:⽆符号的⾃然数,24个⽐特表⽰,仅表⽰帧负载(Frame Payload)所占⽤字节数,不包括帧头所占⽤的9个字节。

默认⼤⼩区间为为0~16,384(2^14),⼀旦超过默认最⼤值2^14(16384),发送⽅将不再允许发送,除⾮接收到接收⽅定义的
SETTINGS_MAX_FRAME_SIZE(⼀般此值区间为2^14 ~ 2^24)值的通知。

帧类型Type:8个⽐特表⽰,定义了帧负载的具体格式和帧的语义,HTTP/2规范定义了10个帧类型,这⾥不包括实验类型帧和扩展类型帧
帧的标志位Flags:8个⽐特表⽰,服务于具体帧类型,默认值为0x0。

有⼀个⼩技巧需要注意,⼀般来讲,8个⽐特可以容纳8个不同的标志,⽐如,PADDED值为0x8,⼆进制表⽰为00001000;
END_HEADERS值为0x4,⼆进制表⽰为00000100;END_STREAM值为0X1,⼆进制为00000001。

可以同时在⼀个字节中传达三种标志位,⼆进制表⽰为00001101,即0x13。

因此,后⾯的帧结构中,标志位⼀般会使⽤8个⽐特表⽰,若某位不确定,使⽤问号?
替代,表⽰此处可能会被设置标志位
帧保留⽐特为R:在HTTP/2语境下为保留的⽐特位,固定值为0X0
流标识符Stream Identifier:⽆符号的31⽐特表⽰⽆符号⾃然数。

0x0值表⽰为帧仅作⽤于连接,不⾪属于单独的流。

关于帧长度,需要稍加关注: - 0 ~ 2^14(16384)为默认约定长度,所有端点都需要遵守 - 2^14 (16,384) ~ 2^24-1(16,777,215)此区间数值,需要接收⽅设置SETTINGS_MAX_FRAME_SIZE参数单独赋值 - ⼀端接收到的帧长度超过设定上限或帧太⼩,需要发送
FRAME_SIZE_ERR错误 - 当帧长错误会影响到整个连接状态时,须以连接错误对待之;⽐如
HEADERS,PUSH_PROMISE,CONTINUATION,SETTINGS,以及帧标识符不该为0的帧等,都需要如此处理 - 任⼀端都没有义务必须使⽤完⼀个帧的所有可⽤空间 - ⼤帧可能会导致延迟,针对时间敏感的帧,⽐如RST_STREAM, WINDOW_UPDATE, PRIORITY,需要快速发送出去,以免延迟导致性能等问题
HTTP2 的帧包含下⾯⼏种类型,对应上图的Type区域定义。

Frame Type Code
DATA 0x0
HEADERS 0x1
PRIORITY 0x2
RST_STREAM 0x3
SETTINGS 0x4
PUSH_PROMISE 0x5
PING 0x6
GOAWAY 0x7
WINDOW_UPDATE 0x8
CONTINUATION 0x9
帧的标志位(Flags)含义如下图:
案例:
假设我们要发送 0x12345678,流编号为 10 ,类型为DATA,那么这个Frame的16进制表达就是:
'000004' + '00' + '00' + '0000000A' + '12345678'
HTTP2 的 Header 帧
HTTP2的 HEADER帧的格式如下:
对应的字段列表说明如下:
- Pad Length:受制于PADDED标志控制是否显⽰,8个⽐特表⽰填充的字节数。

可选。

Flags:PADDED 设置后要求有此字段
- E:⼀个⽐特表⽰流依赖是否专⽤,可选项,只在流优先级PRIORITY被设置时有效可选。

Flags:PRIORITY 设置后要有此字段
- Stream Dependency:31个⽐特表⽰流依赖,只在流优先级PRIORITY被设置时有效可选。

Flags:PRIORITY 设置后要有此字段
- Weight:8个⽐特(⼀个字节)表⽰⽆符号的⾃然数流优先级,值范围⾃然是(1~256),或称之为权重。

只在流优先级PRIORITY被设置时有效这个字段是可选的,并且只在优先级标记设置的情况下才呈现。

- Header Block Fragment:报头块分⽚
- Padding:填充的字节,受制于PADDED标志控制是否显⽰,长度由Pad Length字段决定
注意,只有 Header Block Fragment 是必须的,其他都看帧的标志位Flags 是否设置要有。

所需标志位:
END_STREAM (0x1): 报头块为最后⼀个,意味着流的结束。

END_HEADERS (0x4): 此报头帧不需分⽚,完整的⼀个帧。

后续不再需要CONTINUATION帧帮忙凑齐。

若没有此标志的HEADER 帧,后续帧必须是以CONTINUATION帧传递在当前的流中,否则接收者需要响应PROTOCOL_ERROR类型的连接错误。

PADDED (0x8): 需要填充的标志
PRIORITY (0x20): 优先级标志位,控制独⽴标志位E,流依赖,和流权重。

注意事项:
- 其负载为报头块分⽚,若内容过⼤,需要借助于CONTINUATION帧继续传输。

若流标识符为0x0,结束段需要返回PROTOCOL_ERROR 连接异常。

HEADERS帧包含优先级信息是为了避免潜在的不同流之间优先级顺序的⼲扰。

- 其实⼀般来讲,报⽂头部不⼤的情况下,⼀个HEADERS就可以完成了,特殊情况就是Cookie字段超过16KiB⼤⼩,不常见。

HTTP2的 CONTINUATION 帧
HTTP2的 CONTINUATION 帧的格式如下:
字段列表:
- Header Block Fragment,⽤于协助HEADERS/PUSH_PROMISE等单帧⽆法包含完整的报头剩余部分数据。

注意事项:
- ⼀个HEADERS/PUSH_PROMISE帧后⾯会跟随零个或多个CONTINUATION,只要上⼀个帧没有设置END_HEADERS标志位,就不算⼀个帧完整数据的结束。

- 接收端处理此种情况,从开始的HEADERS/PUSH_PROMISE帧到最后⼀个包含有END_HEADERS标志位帧结束,合并的数据才算是⼀份完整数据拷贝
- 在HEADERS/PUSH_PROMISE(没有END_HEADERS标志位)和CONTINUATION帧中间,是不能够掺杂其它帧的,否则需要报PROTOCOL_ERROR错误
标志位: * END_HEADERS(0X4):表⽰报头块的最后⼀个帧,否则后⾯还会跟随CONTINUATION帧。

HTTP2的 Data帧
⼀个或多个DATA帧作为请求、响应内容载体,较为完整的结构如下:
字段:
Pad Length: ⼀个字节表⽰填充的字节长度。

取决于PADDED标志是否被设置.
Data: 这⾥是应⽤数据,真正⼤⼩需要减去其他字段(⽐如填充长度和填充内容)长度。

* Padding: 填充内容为若⼲个0x0字节,受PADDED标志控制是否显⽰。

接收端处理时可忽略验证填充内容。

若验证,可以对⾮0x0内容填充回应PROTOCOL_ERROR类型连接异常。

标志位:
END_STREAM (0x1): 标志此帧为对应标志流最后⼀个帧,流进⼊了半关闭/关闭状态。

PADDED (0x8): 负载需要填充,Padding Length + Data + Padding组成。

注意事项:
- 若流标识符为0x0,接收者需要响应PROTOCOL_ERROR连接错误
- DATA帧只能在流处于"open" or "half closed (remote)"状态时被发送出去,否则接收端必须响应⼀个STREAM_CLOSED的连接错误。

若填充长度不⼩于负载长度,接收端必须响应⼀个PROTOCOL_ERROR连接错误。

例⼦
其中⼀个⽹络请求包的内容如下图截图:
这⾥⿊⾊加量的部分是 RPC 特有的部分内容。

这部分包含2个帧,他们的分别数据如下:
00 00-0E 01 04 00 00 00 01 88 5F 8B 1D 75 D0 62 0D 26-3D 4C 4D 65 64
00 00 12 00 00 00 00 00 01 00 00-00 00 0D 0A 0B 48 65 6C 6C 6F 20 77 6F 72 6C 64
Header 帧
00 00 0E 01 04 00 00 00 01 88 5F 8B 1D 75 D0 62 0D 26 3D 4C 4D 65 64
帧长度Length 为 00 00 0E ,即 14 + 9 长度共23 。

帧类型Type 为 01 标⽰是 Header 帧
帧的标志位Flags 为 04, 标⽰ END_HEADERS,即这个Header帧不需要分⽚。

流标识符Stream Identifier 为 00 00 00 01 即,编号为1 。

Data帧
00 00 12 00 00 00 00 00 01 00 00 00 00 0D 0A 0B 48 65 6C 6C 6F 20 77 6F 72 6C 64
帧长度Length 为 00 00 12 即 18+9 = 27
帧类型Type 为 00 标⽰是 Data 帧
帧的标志位Flags 00
流标识符Stream Identifier 为 00 00 00 01 ,及编号1,对应上⾯的 Header 帧。

Data帧特有的串(Data 区域): 00 00 00 00 0D 0A 0B 48 65 6C 6C 6F 20 77 6F 72 6C 64
参考资料:
HTTP2协议中报⽂头可以采⽤Haffman编码,我们看到的报⽂头信息都是⼆进制信息。

相关文档
最新文档