深入 HTTP2(帧,消息,流)

http2 协议简介

h2 专注于性能,最大的目标在于用户和网站之间只用一条连接。其h2 的推出并没有改变http1.1 的基本语义。h2的目的是响应复用,头部压缩来提高极致的性能。
其特性在 之前的文章中也做过介绍 https://www.jianshu.com/p/3ea9b33c4678

核心概念
  • 连接 Connection :1个TCP连接包含多个Stream。
  • 数据流 Stream :一个双向通讯数据流,包含1条或多条 message。
  • 消息 Message :对应HTTP/1 中的请求或者响应,包含一个或者多条 Frame
  • 数据帧 : 最小单位,以二进制压缩格式存放 HTTP/1 中的内容。
    深入 HTTP2(帧,消息,流)_第1张图片
    http2

    一个消息是由 Headers 帧和DATA 帧组成的。
    深入 HTTP2(帧,消息,流)_第2张图片
    消息的组成

    流,消息,帧 之间的关系
    深入 HTTP2(帧,消息,流)_第3张图片
    流,消息,帧 之间的关系

抓包可以看到 1号 Stream 流 传递了 一个 GET 请求。1号 Stream 流也进行了回复(HEADER+DATA)


深入 HTTP2(帧,消息,流)_第4张图片
http2抓包

在一条 Connection 中,不同的流可以穿插传递,但是同一条流的达到顺序必须是有序的,比如1号流,流内的 帧必须有序。
这就是传输中无序,接收时组装

深入 HTTP2(帧,消息,流)_第5张图片
多路复用

帧格式

每个帧标准为9个字节 (可理解为帧头)

深入 HTTP2(帧,消息,流)_第6张图片
帧格式

帧中指明了其所属于哪一个 Stream流 (Stream Identifier)其占了31 位。
由此可见,一个帧中最重要的就是 Stream Id 了。其余的内容为

  • Length : 代表整个 frame 的长度,用一个 24 位无符号整数表示
  • Type : 定义 frame 的类型。帧类型决定了帧主体的格式和语义,如果 type 为 unknown 应该忽略或抛弃。
  • Flags :是为帧类型相关而预留的布尔标识。标识对于不同的帧类型赋予了不同的语义。
  • R: 是一个保留的比特位。这个比特的语义没有定义,发送时它必须被设置为 (0x0), 接收时需要忽略。
  • Frame Payload : 是主体内容,由帧类型决定

下图为wireshark中抓取的帧,上述的帧格式可以对比找到


深入 HTTP2(帧,消息,流)_第7张图片
wireshark中的帧

正是将每一个帧关联到流上。才实现了多路复用。这个多路复用指的是很多个流之间的帧随意穿插。比如客户端收到 1流的 1 帧,又收到了 2流的3帧,再收到了3流的4帧,1流的2帧,1流的3帧,3流的5帧。
注意。相同的流之内,其帧必须是按顺序的。
看一下下面的图。还是之前的抓包图


深入 HTTP2(帧,消息,流)_第8张图片
http2抓包

有没有发现除了 0 帧之外,为什么没有偶数帧?1,3,5 。。。
这就是因为 由客户端发起的连接,必须是奇数流。服务端发起的必须是偶数流
一般服务端推送算作是服务端发起的连接,也就会出现偶数流了。

要想实现并发,其实就是建立多个流。因为单个流因为必须顺序发送,所以没有办法做到并发。

  • 流状态管理的约束性规定
    • 新建立的流ID必须大于曾经建立过状态为opened 或者 reserved 的流ID。
    • 在新建立的流ID发送帧时,意味着更小ID为idle的流就必须置为closed了。
    • Stream ID 不能复用,长连接耗尽的ID,只能通过重新建立TCP连接了。

Stream ID 为 0 的帧 是 控制帧,如setting,window_update,ping等帧。

你可能感兴趣的:(深入 HTTP2(帧,消息,流))