HTTP2 协议初识

  RFC:https://tools.ietf.org/html/rfc7540

RFC 中英文对照:https://github.com/fex-team/http2-spec/blob/master/HTTP2%E4%B8%AD%E8%8B%B1%E5%AF%B9%E7%85%A7%E7%89%88(06-29).md

O'Reilly :https://hpbn.co/http2/

SPDY:http://www.chromium.org/spdy/

随着Web应用日渐广泛,复杂程度和重要性也在不断的增长,也因此对开发人员和用户带来了负担,HTTP2 支持所有的HTTP/1.1的核心特征,提供了HTTP语义的传输优化,并且在各方面做到更高效。

HTTP 2 基本概念

HTTP2 是运行在TCP或者SSL协议之上,属于应用层的协议。HTTP2.0消息包以二进制帧的形式进行封装。

HTTP/2 binary framing layer

HTTP2引入了一下的三个新概念:

Stream: 已经建立连接的双向字节流,用唯一ID标示,可以传输一个或多个消息

Message:逻辑上的HTTP消息,请求或者响应,可以包含多个 frame

Frame:HTTP2通信的最小单位,二进制头封装,封装HTTP头部或body

HTTP2是把一个HTTP数据包分成多个帧发送,每个帧有一个二进制头,并把HTTP分成多个独立小帧,多个帧组成一个Message在流中发送。不同流的帧有可能交错到达,帧的报文头中标示了属于哪一个流。

HTTP/2 streams, messages, and frames

HTTP2 的帧格式

HTTP2的最小数据单位是帧,所有帧以9字节的帧头并跟着0-16,383字节的数据。

Frame Layout

Length: unsigned 24-bit integer,最大值为 2^24(16384),指的是不包括头部的部分

Type:帧的类型

Flags:为帧类型保留的8字节字段有具体的布尔标识

R:1位的保留字段

Stream Identifier:31字节的流标识符。0是保留的,标明帧是与连接相关作为一个整体而不是一个单独的流。

帧主体的结构和内容完全取决于帧类型。

HTTP2 有以下十种帧类型:

Frame Type Registry

1、DATA :数据帧,Type=0x0,主要用来传递消息体

DATA Frame Payload

Pad Length : 8位,可选,只在设置了PADDED标记时呈现。表示帧填充的字节为单位的长度。

Data : 应用数据。

Padding : 填充字节不包含任何应用语义值。填充字节在发送时设为0,接收时忽略。

DATA 帧定义了以下的 Flags:

END_STREAM (0x1): 位1,表示当前帧是相应流发送的最后一帧。设置时流进入半封闭或关闭状态。

PADDED (0x8): 位4,表示Pad Length 字段启用与否。

2、HEADERS :头部帧,Type=0x1,主要用于传递消息头

HEADERS Frame Payload

Pad Length:8位可选,在设置PADDED 标记时呈现。表示帧填充的字节为单位的长度。

E : 1位可选,在优先级标记设置时呈现。表示用于标识流依赖是否是专用的。

Stream Dependency : 31位可选,在优先级标记设置时呈现。流依赖的流的标识符。

Weight : 8位可选,在优先级标记设置时呈现。流的8位权重标记,1-256的值。

Header Block Fragment : 报头块。

Padding : 填充字节

HEADERS 帧定义了以下的 Flags:

END_STREAM (0x1) : 位1,标识是此发送端对流发送的最后报头区块。设置这标记使流进入半封闭状态。

END_HEADERS (0x4) : 位3,表示帧包含了整个的报头块,且后面没有延续帧。 END_HEADERS为0的报头帧后面必须跟着延续帧。

PADDED (0x8) : 位4,表示Pad Length字段会呈现。

PRIORITY (0x20) : 位6,优先级标记(E), 流依赖及权重字段将会呈现。

3、PRIORITY :优先级帧,Type=0x2,用于设置流的优先级

PRIORITY Frame Payload

E : 1位标记,指示流的依赖是专有的。

Stream Dependency : 流所依赖流的31位标识符。

Weight: 流的权重(8位)。1-256的权重值。

4、RST_STREAM :流结束帧,Type=0x3,用于终止异常流

RST_STREAM Frame Payload

RST_STREAM 帧由一个32位整数标记错误码,指明流被终止的原因。

RST_STREAM 帧必须与流相关联,就是说stream id 不能为 0x0

RST_STREAM帧绝对不能在流处于“空闲”状态下发送。

5、SETTINGS :连接配置参数帧,Type=0x4,用于设置参数

Setting Format

载体包含0或多个参数,每个包含一个16位标识以及一个32位的值。

1)设置帧由两个终端在连接开始时发送,连接生存期的任意时间发送。

2)设置帧的参数将替换参数中现有值,不能识别的忽略。

3)设置帧总是应用于连接,而不是一个单独的流。流ID必须为0;

SETTINGS 帧定义了以下的 Flags:

ACK (0x1) : 位1,表示设置帧被接收端接收并应用。如果设置了ACK,设置帧的载体必须为空。

Settings Registry

SETTINGS_HEADER_TABLE_SIZE (0x1) : 发送端通知远端报头压缩表的最大承载量。初始值是4,096个字节。

SETTINGS_ENABLE_PUSH (0x2) : 用来关闭服务器推送。0时不能发送PUSH_PROMISE。1表示可以推送。

SETTINGS_MAX_CONCURRENT_STREAMS (0x3) : 标明发送端允许接收端创建的最大并发流的数量。没有限制(<100) 。 0值阻止新流的创建。

SETTINGS_INITIAL_WINDOW_SIZE (0x4) : 表示发送端流量控制的初始窗口大小(字节)。初始值是65,535。 影响所有流的窗口大小.

SETTINGS_MAX_FRAME_SIZE (0x5): 接收最大帧大小。初始值为2^14 (16,384)字节,最大值为2^24-1 or 16,777,215字节。

SETTINGS_MAX_HEADER_LIST_SIZE (0x6): 可接收的header列表长度(字节),基于非压缩的列表大小。

6、PUSH_PROMISE:推送承诺帧,Type=0x5,Server推送之前告知Client端

PUSH_PROMISE Payload Format

1) 被推送的流并不需要按照顺序使用。

2) 接收端可以给推送端返回一个RST_STREAM拒绝接收。

Pad Length : 8位,只在PADDED标记设置时才呈现。

R : 1bit保留位。Padding : 填充字节。

Promised Stream ID : 31位整数表示终端准备发送的流标记。

Header Block Fragment : 包含请求头字段的报头区块。

PUSH_PROMISE 帧定义了以下的Flags:

END_HEADERS (0x4) : 位3, 表明帧包含了整个报头区块。

PADDED (0x8) : 位4, 表明Pad Length字段是已设置。

7、PING:Type=0x6,发送端测量最小的RTT时间,检测连接是否可用

PING Payload Format

PING 帧定义了以下的Flags:

ACK (0x1) : 位1表示PING帧是一个PING响应。

1)PING帧可以被任何终端任何时刻发送。

2)PING帧必须在载体中包含一个8字节长度的数据。

收到不含ACK的PING帧必须发送一个有ACK的PING响应,带相同的载荷。PING响应应设置比其他帧更高的优先级。流ID为0,不和任何流关联;

8、GOAWAY:超时帧,Type=0x7,通知对端不要在连接上建新流

GOAWAY Payload Format

可以由客户端或服务端发送。发动端将忽略连接上流标示符大于Last-Stream-ID的流。

接收端接收到超时帧后不能在这个连接上打开新流,可以创建新连接。

终端在关闭连接之前总是应当发送一个超时帧;

适用于连接而不是特定的流。流标识符必须是0x0,否则错误处理;

连接关闭前小于或等于标识符上的流没有完全关闭的,重试请求;

小于或等于最后流标识符的流可能仍然能成功完成,保持连接在打开状态直到正在处理的流全部处理完成。

在发送超时帧后,发送端能丢弃流标识符大于最终流标识的流的帧。但任何修改流状态的帧不能被忽略。

超时帧包含一个32位错误码,包含关闭连接的原因。

9、WINDOW_UPDATE:Type=0x8,实现流量控制

WINDOW_UPDATE Payload Format

1) 可以作用单独的流(ID!=0) 或 整个连接(ID==0)

2) 所有类型的流量控制都是逐跳的(hop-by-hop), 中介端不会转发

3) 流量控制只适用于Data帧

4) 一个保留字节,一个31位整数( 发送端被允许传输的字节数,它的大小是接收端的缓存能力的衡量)。

5) 流和连接的初始值都是65535;流的窗口大小可以用SETTING帧设置大小SETTINGS_INITIAL_WINDOW_SIZE;

6) 通过设置窗口大小,可能导致窗口大小为负数(当前有10字节数据,设置为5字节,则剩余-5字节的长度)。

10、CONTINUATION:延续帧,Type=0x9,延续一个报头区块

CONTINUATION Frame Payload

只要流上前一帧是不带END_HEADERS的HEADERS帧、PUSH_PROMISE帧或者不带有END_HEADERS标记的CONTINUATION帧,可以发送任意多个延续帧。

CONTINUATION 帧定义了以下的Flags:

END_HEADERS (0x4) : 位3,指示帧是否是报头区块的终止。 如果END_HEADERS位没有被设置,这个帧必须跟着另一个延续帧。

HTTP2 错误码

Error Code Registry

HTTP2 连接过程

http2 的版本标识:

h2:基于TLS之上构建的HTTP/2,作为ALPN的标识符,两个字节表示,0x68, 0x32,即https

h2c:直接在TCP之上构建的HTTP/2,缺乏安全保证,即http

HTTP版本的请求过程:

在不知道服务器是否支持http2的情况下,可以利用http的升级机制发送试探包

1、客户端发起请求

2、服务器不支持 http2,直接按照 http/1.1响应

3、服务器支持 http2,通知客户端切换到http2

4、服务器发送的第一个http2帧,必须为SETTINGS帧做为连接序言

5、客户端接收到101响应后,也必须发送一个序言作为响应,其逻辑结构:

6、客户端可以马上发送请求帧或其它帧过去,不用等待来自服务器端的SETTINGS帧

7、任一端接收到SETTINGS帧之后,都需要返回一个包含确认标志位SETTIGN作为确认

8、其它帧的正常传输

HTTP Upgrade

HTTPS 版本的建立连接:

1、客户端和服务器端TLS层协商

2、客户端发送连接序言(同上表示,PRI + SETTINGS)

3、接收到客户端连接序言之后,服务器端发送连接序言

4、双方各自确认SETTINGS帧

5、其它帧的正常传输

ALPN

HTTP/2的直接连接:

1、客户端必须首先发送一个连接序言,其逻辑结构:

2、发送完毕序言之后,客户端可以不用等待来自服务器端响应,马上发送HTTP/2其它帧

3、服务器端接收到客户端的连接序言之后,需要发送一个SETTINGS帧作为连接序言

4、任一端接收到SETTINGS帧之后,都需要返回一个包含确认标志位SETTIGN作为确认

5、其它帧的正常传输

Starting HTTP/2

对比明文版的HTTP/1.1和HTTP/2完成一次请求-响应:

1、HTTP/1.1在建立建立之后,只需要发送请求报文数据

2、HTTP/2客户端需要在连接建立之初马上发送一个连接序言过去,然后才是正常请求

3、两端(客户端+服务器端)的两次完整的连接序言+确认的交互流程,多了两次往返过程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容