这篇文章通过 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
字节。