HTTPS
2.服务端也会发送一个消息,告诉客户端选择使用的协议版本、加密套件、压缩算法等,也有一个随机数
3.随后服务端有一个非对称密钥,将证书发送给客户端,证书里有非对称密钥的公钥
4.客户端从信任的CA中拿到公钥解密这个证书,成功说明网站可信.并计算Pre-Master随机数,以非对称密钥的公钥加密
5.服务端用非对称加秘的私钥解密拿出Pre-Master随机数
6客户端与服务端同时计算数据传输时的对称公钥;对称密钥=客户端的随机数+服务端的随机数+Pre-Master随机数
HTTP2
流
HTTP 2.0 协议将一个 TCP 的连接中,分成多个流,每个流都有自己的 ID,是一串有先后顺序的数据流,这些数据流按照次序组装起来.流同时发送多个“碎片化”的消息,这就是常说的“多路复用”多个往返通信都复用一个连接来处理。
帧
HTTP 2.0 还将所有的传输信息分割为更小的帧,并对它们采用二进制格式编码。常见的帧有 Header 帧,用于传输 Header 内容,并且会开启一个新的流。再就是 Data 帧,用来传输正文实体。多个 Data 帧属于同一个流。在“流”的层面上看,消息是一些有序的“帧”序列,而在“连接”的层面上看,消息却是乱序收发的“帧”。多个请求 / 响应之间没有了顺序关系,不需要排队等待,在应用层上也就不会再出现“队头阻塞”问题,降低了延迟,大幅度提高了连接的利用率。
HTTP3.0
HTTP 2.0 虽然大大增加了并发性,但还是有问题的。因为 HTTP 2.0 也是基于 TCP 协议的,TCP 协议在处理包时是有严格顺序的。
假如客户端用 TCP 发送了三个包,但服务器所在的操作系统只收到了后两个包,第一个包丢了。那么内核里的 TCP 协议栈就只能把已经收到的包暂存起来,“停下”等着客户端重传那个丢失的包,这样就又出现了“队头阻塞”
这种“队头阻塞”是 TCP 协议固有的,所以Google 的 QUIC 协议基于UDP
包
帧
连接机制
QUIC 基于 UDP,根本没有握手和挥手,所以QUIC 也基于 UDP 实现了可靠传输.在 QUIC 自己的逻辑里面维护连接的机制,是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。
假如手机由 4G 切换到 WiFi。这时 IP 地址会发生变化,TCP 就必须重新建立连接。而 QUIC 连接里的两端连接 ID 不会变,所以连接在“逻辑上”没有中断,它就可以在新的 IP 地址上继续使用之前的连接,消除重连的成本,实现连接的无缝迁移。
重传机制
在 TCP 里面超时的采样存在不准确的问题。例如,发送一个包,序号为 100,发现没有返回,于是再发送一个 100,过一阵返回一个 ACK101。这个时候客户端知道这个包肯定收到了,但是往返时间是多少呢?是 ACK 到达的时间减去后一个 100 发送的时间,还是减去前一个 100 发送的时间呢?事实是,第一种算法把时间算短了,第二种算法把时间算长了。
QUIC 也有个序列号,是递增的。QUIC 还定义了一个 offset 来记录数据流。任何一个序列号的包只发送一次,下次就要加一了。例如,发送一个包,序号是 100,发现没有返回;再次发送的时候,序号就是 101 了;如果返回的 ACK 100,就是对第一个包的响应。如果返回 ACK 101 就是对第二个包的响应,RTT 计算相对准确。
无阻塞的多路复用
同 HTTP 2.0 一样,同一条 QUIC 连接上可以创建多个 stream,来发送多个 HTTP 请求。但是,QUIC 是基于 UDP 的,一个连接上的多个 stream 之间没有依赖。这样,假如 stream2 丢了一个 UDP 包,后面跟着 stream3 的一个 UDP 包,虽然 stream2 的那个包需要重传,但是 stream3 的包无需等待,就可以发给用户。
流量控制
QUIC 的流量控制也是通过滑动窗口.在一个连接上控制窗口,而且还在一个连接中的每个 stream 控制窗口。
QUIC 的 ACK 是基于 offset 的,每个 offset 的包来了,进了缓存,就可以应答,应答后就不会重发,中间的空挡会等待到来或者重发即可,而窗口的起始位置为当前收到的最大 offset,从这个 offset 到当前的 stream 所能容纳的最大缓存,是真正的窗口大小。显然,这样更加准确。
参考资料:
<极客时间>-趣谈网络协议