前言
HTTP/2协议在TCP链接之初进行协商通讯,只有协商成功,才会涉及到后续的请求-响应等具体的业务型数据交换。html
HTTP版本标识符
- h2,基于TLS之上构建的HTTP/2,做为ALPN的标识符,两个字节表示,0x68, 0x32,即https
- h2c,直接在TCP之上构建的HTTP/2,缺少安全保证,即http
- 在HTTP/2 RFC文档出现以前,以上版本字段须要添加上草案版本号,相似于h2-11,h2c-17
HTTP/2 请求过程
针对直接创建在标准TCP之上HTTP2,在未知服务器是否提供HTTP/2支持以前,能够依赖现有HTTP/1.1进行试探。java
HTTP版本的请求内容
- 客户端发起请求,只有请求报头:
GET / HTTP/1. 1 Host: server. example. com Connection: Upgrade, HTTP2-Settings Upgrade: h2c HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>
- 服务器若不支持HTTP/2,直接按照HTTP/1.1响应便可
HTTP/1. 1 200 OK Content-Length: 243 Content-Type: text/html . . .
-
服务器支持HTTP/2,通知客户端一块儿切换到HTTP/2协议下吧安全
HTTP/1. 1 101 Switching Protocols Connection: Upgrade Upgrade: h2c [ HTTP/2 connection . . .
- 101响应空行以后,服务器必须发送的第一个帧为SETTINGS帧(其负载可能为空)做为链接序言
- 客户端接收到101响应后,也必须发送一个序言做为响应,其逻辑结构:
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n // 纯字符串表示,翻译成字节数为24个字节 SETTINGS帧 // 其负载可能为空
服务器端和客户端所发送的链接序言有所不一样。
- 客户端能够立刻发送请求帧或其它帧过去,不用等待来自服务器端的SETTINGS帧
- 任一端接收到SETTINGS帧以后,都须要返回一个包含确认标志位SETTIGN做为确认
- 其它帧的正常传输
HTTP/2的直接链接
客户端预先知道服务器提供HTTP/2支持,能够免去101协议切换的流程开销。 具体流程:服务器
- 客户端必须首先发送一个链接序言,其逻辑结构:
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n // 纯字符串表示,翻译成字节数为24个字节 SETTINGS帧 // 其负载可能为空
- 发送完毕序言以后,客户端能够不用等待来自服务器端响应,立刻发送HTTP/2其它帧
- 服务器端接收到客户端的链接序言以后,须要发送一个SETTINGS帧做为链接序言
- 任一端接收到SETTINGS帧以后,都须要返回一个包含确认标志位SETTIGN做为确认
- 其它帧的正常传输
HTTPS版本创建链接
HTTP/2安全版本在TLS上构建,协商采用的ALPN扩展协议,采用“h2”做为协议标识符(http版本则是“h2c”)。必定程度上可认为不存在试探是否支持或直接链接的烦恼,由于这个过程直接在TLS层协商而成。网络
流程以下:url
- 客户端和服务器端TLS层协商
- 客户端发送链接序言(同上表示,PRI + SETTINGS)
- 接收到客户端链接序言以后,服务器端发送链接序言
- 双方各自确认SETTINGS帧
- 其它帧的正常传输
HTTPS和HTTP Upgrade方式协商
HTTPS协商是强制,封装在TLS之上ALPN扩展实现,HTTP只有非直接链接方式才会存在经过101 协议切换方式进行升级。spa
这里有一张图形象说明其流程。.net

统一的链接过程
这里不管是HTTP仍是HTTPS,在两端成功协商以后(或HTTP的直接链接),其链接过程都是同样的翻译

注意事项
- 客户端发起的HTTP/1.1请求,其流标识符为1,默认优先级;半关闭“half closed”状态,一旦完成HTTP/2的链接,将被应用于响应
- 文档提到的客户端能够经过HTTP Alternative Services(简称为[ALT-SVC],相似于CNAME机制)得到通知服务器是否支持HTTP/2,但目前看来仅仅是草案建议而已
- 链接序言用于最后两端协商确认双方要使用HTTP/2协议,创建初始化的HTTP/2链接环境
- 客户端若知服务器支持HTTP/2,可免去经过HTTP/1.1 101协议切换方式进行升级,在创建链接后便可发送序言,不然只能在接收到服务器端101响应后发送序言
- 创建在TLS上的HTTP/2经过ALPN扩展协商机制取代101协议切换
- 链接序言所包含的SETTINGS帧其负载能够为空
- 针对一个TCP链接,服务器第一个要发送的帧必须是SETTINGS帧
- 为了不没必要要延迟,客户端能够在发送完毕序言以后发送帧数据,不用等待来自服务器端的序言SETTINGS帧
- 客户端接收到服务器端做为序言的SETTINGS帧,须要遵照其设定
- 在一些环境下须要提供一个顺序机制,容许服务器在客户端发送业务帧以前发送SETTINGS,这须要客户端配合
- 客户端和服务器端任何一方接收到无效链接序言须要抛出PROTOCOL_ERROR类型链接错误,若收到GOAWAY帧,可忽略
小结
HTTP/2链接的创建协商机制比HTTP/1.1稍微复杂了一些。code
对比明文版的HTTP/1.1和HTTP/2完成一次请求-响应:
- HTTP/1.1在创建创建以后,只须要发送请求报文数据
- HTTP/2客户端须要在链接创建之初立刻发送一个链接序言过去,而后才是正常请求
- 两端(客户端+服务器端)的两次完整的链接序言+确认的交互流程,多了两次往返过程
在弱网络环境下,会不会加剧网络负载,只能拭目一看了。
引用
- 《Implementing HTTP/2 client in 60 minutes》
原文 http://www.blogjava.net/yongboy/archive/2015/03/18/423570.html