HTTP/2笔记之连接建立
前言
HTTP/2协议在TCP连接之初进行协商通信,只有协商成功,才会涉及到后续的请求-响应等具体的业务型数据交换。
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进行试探。
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层协商而成。
流程如下:
- 客户端和服务器端TLS层协商
- 客户端发送连接序言(同上表示,PRI + SETTINGS)
- 接收到客户端连接序言之后,服务器端发送连接序言
- 双方各自确认SETTINGS帧
- 其它帧的正常传输
HTTPS和HTTP Upgrade方式协商
HTTPS协商是强制,封装在TLS之上ALPN扩展实现,HTTP只有非直接连接方式才会存在通过101 协议切换方式进行升级。
这里有一张图形象说明其流程。

统一的连接过程
这里不论是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稍微复杂了一些。
对比明文版的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
HTTP/2笔记之连接建立的更多相关文章
- 《TCP/IP详解 卷一》读书笔记-----TCP连接建立
1.在每个TCP报文段中,头部的flag字段里的SYN,FIN,RST,PSH可以多个有效,并没有限定为必须只有一个 2.TCP连接建立过程: 1)客户端发送一个SYN报文段,其中包含了客户端要传送的 ...
- gRPC的通讯过程
在 HTTP2 协议正式开始工作前, 如果已经知道服务器是 HTTP2 的服务器, 通讯流程如下: 客户端必须首先发送一个连接序言,其逻辑结构: PRI * HTTP/2.0\r\n\r\nSM\r\ ...
- eShopOnContainers 知多少[11]:服务间通信之gRPC
引言 最近翻看最新3.0 eShopOncontainers源码,发现其在架构选型中补充了 gRPC 进行服务间通信.那就索性也写一篇,作为系列的补充. gRPC 老规矩,先来理一下gRPC的基本概念 ...
- memcached客户端连接建立过程笔记
memcached在启动过程初始化server_sockets时,根据启动参数决定系统是进行tcp监听还是udp监听,这里暂时只关注tcp的情况. server_socket在初始化时会向系统申请监听 ...
- Android学习笔记之HttpClient实现Http请求....
PS:最近光忙着考试了....破组成原理都看吐了....搞的什么也不想干...写篇博客爽爽吧....貌似明天就考试了...sad... 学习笔记: 1.如何实现Http请求来实现通信.... 2.解决 ...
- 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(1)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(2)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- think in java 读书笔记 2 —— 套接字
目录 think in java 读书笔记 1 ——移位 think in java 读书笔记 2 —— 套接字 think in java 读书笔记 3 —— 数据报 概要 1. 套接字基本知识 2 ...
- DBus学习笔记
摘要:DBus作为一个轻量级的IPC被越来越多的平台接受,在MeeGo中DBus也是主要的进程间通信方式,这个笔记将从基本概念开始记录笔者学习DBus的过程 [1] DBus学习笔记一:DBus学习的 ...
随机推荐
- MySQL 时间戳(Timestamp)函数
1. MySQL 获得当前时间戳函数:current_timestamp, current_timestamp() mysql> select current_timestamp, curren ...
- WARNING: arch/arm/mach-omap2/built-in.o(.text+0x12cdc): Section mismatch in reference from the function mmc0_init() to the (unknown reference) .init.data:(unknown)
解决方法,找到对应的不能使用 __init 字眼的地方,删除他即可. 最后删除 296 static struct omap2_hsmmc_info am335x_mmc[] __initdata = ...
- USB 之传输编码格式 NRZI 介绍
记录NRZI (Non-Return-to-Zero Inerted code) 非归零翻转编码,之前,我先稍微记录一下他的前身. RZ 编码(Return- to - zero coding) RZ ...
- 课后作业——用lastIndexOf判断是否是字符串的最后一位
package test; public class Testlianxi { public static void main(String[] args) { //判断fgh是否是字符串的最后一位 ...
- Zookeeper配置文件参数与含义
zoo.cfg # The number of milliseconds of each tick tickTime=2000 # The number of ticks that the ini ...
- java多线程有几种实现方法?线程之间如何同步
java中多线程的实现方法有两种:1.直接继承thread类:2.实现runnable接口: 同步的实现方法有五种:1.同步方法:2.同步代码块:3.使用特殊域变量(volatile)实现线程同步:4 ...
- linux大小写转换
[root@ob2 mytmp]# cat aa2.txt|sed 's#[a-z]#\u&#g'ETH0 LINK ENCAP:ETHERNET HWADDR 00:0C:29: ...
- 利用CMake和OpenCV源代码生成Visual Studio工程
OpenCV1.0版本有windows,linux之分,笔者曾经一直使用Opencv1.0.这个版本在下载,安装之后,在 \OpenCV\_make文件夹下面已经存在了一个opencv.dsw的工程文 ...
- c++下面的一个单例
Public FileManager { private FileManager(); public static FileManager Instance=new FileManager(); } ...
- YUV数据YUY2到I420
/* 主要的采样格式有YCbCr 4:2:0.YCbCr 4:2:2.YCbCr 4:1:1和 YCbCr 4:4:4.其中YCbCr 4:1:1 比较常用,其含义为:每个点保存一个 8bit 的亮度 ...