这篇文章通过 Wireshark 抓包工具逐步分析 HTTP/2 协议中 帧(frame)、消息(message)、流(stream) 三者之间的关系,加深对 HTTP/2 协议的理解。
1.HTTP/2 核心概念
- 连接
Connection:1个TCP连接,包含一个或者多个Stream。 - 数据流
Stream:一个双向通讯数据流,包含1条或者多条Message。 - 消息
Message:对应HTTP/1中的请求或者响应,包含一条或者多条Frame。 - 数据帧
Frame:最小单位,以二进制压缩格式存放HTTP/1中的内容。
2.帧(frame)、流(stream)、消息(message)示意图
Tips:图中
Stream表示多个数据流,它们可以源源不断地并发传送,同一个Stream流中的frame数据是串行发送的。
3.帧头部(9字节)示意图
4.标准帧数据示意图
5.Stream ID 的作用
5.1 实现多路复用
- 接收端的实现可据此并发组装消息
- 同一
Stream内的frame必须是有序的(同一Stream内的frame是串行的) SETTINGS_MAX_CONCURRENT_STREAMS控制着并发Stream数
5.2 同一组 Stream 流数据示意图
下面展示的是同一组 Stream ID 值为 3 的 HEADERS 帧数据:
5.3 推送依赖性
- 由客户端建立的
Stream ID必须是奇数。 - 由服务端建立的
Stream ID必须是偶数(如服务端主动向客户端推送消息)。
Tips:
Stream ID为0的流仅用于传输控制帧。
5.4 流状态约束
- 新建立的
Stream ID必须大于曾经建立过的状态为opened或reserved的Stream ID。 - 在新建立的流上发送帧时,意味着将更小
ID且为idle状态的Stream设置为Closed状态。 Stream ID不能复用,长连接耗尽ID应创建新连接。
6.帧类型
| 帧类型 | 类型编码 | 含义 |
| DATA | 0x0 | 传递 HTTP 包体 |
| HEADERS | 0x1 | 传递 HTTP 头部 |
| PRIORITY | 0x2 | 指定 Stream 流的优先级 |
| RST_STREAM | 0x3 | 终止 Stream 流 |
| SETTINGS | 0x4 | 修改连接或者 Stream 流的配置 |
| PUSH_PROMISE | 0x5 | 服务端推送资源时描述请求的帧 |
| PING | 0x6 | 心跳检测,兼具计算 RTT 往返时间的功能 |
| GOAWAY | 0x7 | 优雅的终止连接或者通知错误 |
| WINDOW UPDATE | 0x8 | 实现流量控制 |
| CONTINUATION | 0x9 | 传递较大 HTTP 头部时的持续帧 |
Tips:心跳往返都是
PING,WebSocket中往返心跳对应PING、PONG。
7.SETTINGS 帧抓包分析
7.1 SETTINGS 帧类型
| SETTINGS 帧类型 | 含义 |
| SETTINGS_HEADERS_TABLE_SIZE(0x1) | 通知对端索引表的最大尺寸(单位字节,初始 4096 字节) |
| SETTINGS_ENABLE_PUSH(0x2) | Value 设置为 0 时可禁用服务器推送功能, 1 表示启用 |
| SETTINGS_MAX_CONCURRENT_STREAMS(0x3) | 告诉接收端允许的最大并发 Stream 数量 |
| SETTINGS_INITIAL_WINDOW_SIZE(0x4) | 声明发送端的窗口大小,用于 Stream 级别流控,初始值 2^16-1,即 65535字节 |
| SETTINGS_MAX_FRAME_SIZE(0x5) | 设置帧的最大大小,初始值 2^14,即 16384 字节 |
| SETTINGS_MAX_HEADER_LIST_SIZE(0x6) | 知会对端头部索引表的最大尺寸,单位字节,基于未压缩前的头部 |
7.2 抓取客户端首次 SETTINGS 帧
下面还是以抓取 www.sina.com.cn 首页数据为例,然后使用 显示过滤器只显示 HTTP/2 部分的数据,下面抓取的是 Stream 中首帧,客户端握手的数据:
Tips:从图中可以看出客户端
Settings - Max concurrent streams : 1000表示客户端允许的最大并发Stream数量是1000,。
7.3 抓取服务端首次 SETTINGS 帧
下面抓取 HTTP/2 握手之后服务端发送的首次 SETTINGS 帧数据分析:
Tips:从图中可以看出服务端的
Settings - Max concurrent streams : 128表示服务端允许的最大并发Stream数是128,Settings - Max frame size : 16777215表示服务端允许的最大帧大小16777215字节。





