本文是笔者在网络传输方面的学习笔记
网络传输模型
网络传输的参考模型有两种,一种是OSI(Open System InetConnection)参考模型,其有七层,另一种是TCP/IP参考模型,被减压成四层。OSI模型在当下以基本被TCP/IP模型所取代,使用代价太昂贵,很少公司用得起。如下图所示:
网络数据在传输的过程中是从网络中的一个设备传送给另一个设备。在这个过程中,数据以文本形式存在应用层,以报文形式存在传输层中,以IP数据包形式存在网络层中,而在链路层,则表现为数据帧,在物理层以比特流形式存在,最后转化为电和光信号输出,例如输出到屏幕装置。
网络传输层
为什么我们一般比较关注网络传输层?
因为传输层是面向通信部分的最高层,用户功能中的最底层。是在网络开发中,传输层一般是我们程序员能接触到的最低层次。它是为上面的应用层提供通信服务,提供应用进程间的逻辑通信。
网络传输层我们主要关注两个主要协议:传输控制协议 TCP(Transmission Control Protocol)和用户数据报协议 UDP(User Datagram Protocol)。对于这两种最大不同点就是TCP传输数据是可靠安全的,UDP传输数据是不可靠,但是高效的。
用户数据报协议 UDP 的特点:
(1)面向无连接:不需要像 TCP 一样在发送数据前进行三次握手,想发就直接发了。
(2)有单播、多播、广播功能:支持一对一、一对多、多对多、多对一的方式传输方式。
(3)面向报文:所谓面向报文就是指UDP数据传输的单位是报文,且不会对数据作任何拆分和拼接操作。
(4)不可靠性:无连接发送数据,不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。没有拥塞控制,以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。容易在网络条件不好的情况下导致丢包。
(5)头部开销小:只有 8 字节,相比 TCP 的至少 20 个字节要少得多,在传输数据报文时是很高效的。UDP 头部包括:端口号(源 目的) 报文长度 检验和。
用户数据报协议 TCP的特点:
(1)面向连接:面向连接,是指发送数据之前必须在两端建立连接。建立连接的方法是“三次握手”,建立连接是为数据的可靠传输打下基础。
(2)仅支持单播:每条 TCP 传输连接只能有两个端点,只能进行点对点的数据传输,不支持多播和广播传输方式。
(3)面向字节流:TCP 不像 UDP 一样那样一个个报文独立地传输,而是在不保留报文边界的情况下以字节流方式进行传输。所谓面向字节流指的是 TCP 以字节为单位。虽然传输的过程中数据被划分成一个个数据报,但这只是为了方便传输,接收端最终接受到的数据将与发送端的数据一模一样。
(4)可靠传输:对于可靠传输,判断丢包,误码靠的是TCP的段编号以及确认号。
(5)提供拥塞控制:当网络出现拥塞的时候,TCP能够减小向网络注入数据的速率和数量,缓解拥塞。
(6)提供全双工通信:TCP 允许通信双方的应用程序在任何时候都能发送数据,因为 TCP 连接的两端都设有缓存,用来临时存放双向通信的数据。TCP可以立即发送一个数据段,也可以缓存一段时间以便一次发送更多的数据段。
TCP的可靠服务基础:
TCP协议可靠的连接服务的保证,采用三次握手建立一个连接,如图所示
(1)第一次握手:建立连接时,客户端A发送SYN包(SYN=X)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
(2)第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=X 1),同时自己也发送一个SYN包(SYN=Y),即SYN ACK包,此时服务器B进入SYN_RECV状态。
(3)第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=Y 1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据。
为什么用四次挥手?
主要原因在于 TCP 连接是全双工的,每个方向都必须单独地进行关闭,前两次挥手用于断开一个方向的连接,后两次挥手用于断开另一方向的连接。如图
(1)客户端A发送一个FIN ACK报文,设置发送序号X,用来关闭客户A到服务器B的数据传送。
(2)服务器B收到这个FIN,它发回一个ACK设置发送序号Z,确认序号为收到的序号X加1。
(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A,设置发送序号为Y,确认序号为X。
(4)客户端A发回ACK报文确认,设置发送序号X 1,并将确认序号设置为收到序号Y 1。
网络传输应用层
在因特网中的应用层协议很多,如支持万维网应用的HTTP协议,支持电子邮件的SMTP协议,支持文件传送的FTP协议,DNS,POP3,SNMP,Telnet等等。
HTTP 协议是 HyperText Transfer Protocol(超文本传输协议)的缩写,它是互联网上应用最为广泛的一种网络协议。所有的 WWW 文件都必须遵守这个标准。伴随着计算机网络和浏览器的诞生,HTTP1.0 也随之而来,处于计算机网络中的应用层,HTTP 是建立在 TCP 协议之上,所以HTTP 协议的瓶颈及其优化技巧都是基于 TCP 协议本身的特性,例如 tcp 建立连接的 3 次握手和断开连接的 4 次挥手以及每次建立连接带来的 RTT(Round-Trip Time) 延迟时间。
HTTP/1.x 发布
HTTP/1.x 的缺点在于连接无法复用,连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的下影响明显,慢启动则对大量小文件请求影响较大(没有达到最大窗口请求就被终止)。而且传输数据时,每次都需要重新建立连接,增加延迟。虽然HTTP/1.1 加入 keep-alive 可以复用一部分连接,但域名分片等情况下仍然需要建立多个 connection,耗费资源,给服务器带来性能压力。
HTTP/2 发布
2015 年,HTTP/2 发布。HTTP/2 是现行 HTTP 协议(HTTP/1.x)的替代,但它不是重写,HTTP 方法/状态码/语义都与 HTTP/1.x 一样。HTTP/2 基于 SPDY3,专注于性能,最大的一个目标是在用户和网站间只用一个连接(connection)。HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
QUIC和HTTP/3出现背景
虽然 HTTP/2 解决了很多之前旧版本的问题,但是它还是存在一个巨大的问题,主要是底层支撑的 TCP 协议造成的。虽然 HTTP/2 使用了多路复用,但是通常同一域名下只会建立一个 TCP 连接。如果这个连接中出现了丢包的情况,那就会导致 HTTP/2 的性能急剧下降。比不上HTTP/1。因为发生丢包的情况下,整个 TCP 都要开始等待重传,也就导致了后面的所有数据都被阻塞了。但是对于 HTTP/1.1 来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。我们都很容易想到可以去修改 TCP 协议,但是 TCP 存在的时间太长,广泛应用于各个领域各种设备,并且这个协议是由操作系统实现的,基本无法再修改。基于这个原因,Google 就提出了一个全新的,基于 UDP 协议的 QUIC 协议,并且使用在了 HTTP/3 上,HTTP/3 之前名为 HTTP-over-QUIC,从这个名字可以看出,HTTP/3 的最大改进在于加入了 QUIC协议。QUIC 虽然基于 UDP,但是在原本的基础上新增了很多功能, 在后续章节再详解介绍QUIC 新功能。