网络模型

五层体系结构

在 TCP/IP 网络模型中共分为 5 层,从上到下分别是

应用层

我们使用的软件都是工作在应用层的,专注于为用户提供应用服务,不考虑如何传输。应用层是工作在用户态,而其他层是内核态。

传输层

传输层是给应用层提供数据传输支持的,在传输层有两个协议

网络层

数据链路层

物理层

OSI 网络模型(七层体系结构)

在 TCP/IP 协议模型的基础上,将应用层拆分成了应用层,表示层和会话层

各层都有哪些常见的协议

  • 应用层:HTTP、FTP、TELNET、SMTP、DNS 等
  • 传输层:TCP 和 UDP
  • 网络层:IP、ICMP、ARP

什么是 HTTP 协议

HTTP 协议全称是 Hyper-Text Transfer Protocl 超文本传输协议,所谓超文本就是超越了普通文本的文本,是文本,图片,音视频等的混合体,所以总的来说,HTTP 协议就是用于在计算机中传输文本、图片、音频和视频等超文本数据的规范

HTTP 协议具有以下特性:

  • 简单
  • 灵活易用
  • 应用广泛且跨平台
  • 无状态
  • 明文传输
  • 不安全

针对 HTTP 协议明文传输和不安全的缺点,可以使用 HTTPS 来解决,即引入 SSL/TLS 协议,提高安全性。

HTTPS 解决了什么风险

  • 窃听风险
  • 篡改风险
  • 伪装风险

HTTPS 如何解决的

  • 混合加密:通过对信息加密避免数据被窃听的风险

在通信建立前采用非对称加密的方式交换会话密钥,之后的数据传输都采用对称加密。因为对称加密本质上就是位运算,而非对称加密采用了大量的数学运算,我们都知道计算机执行位运算的效率要远高于数学运算,所以对于相同文本对称加密的效率远高于非对称加密。

  • 摘要算法:提供了数据校验的能力避免被篡改

发送数据时使用摘要算法计算出明文的指纹,并把指纹和明文一起加密成密文发送到对方,对方解密后用相同的摘要算法算出明文的指纹,并和发送时携带的指纹进行比较。

  • 身份证书:使用身份证书保证不会被伪装

服务端将自己的公钥注册到数字证书认证机构(CA),CA 用自己的私钥将服务器的公钥进行数字签名,客户端和服务端建立连接时会验证服务端的证书是否有效。

HTTPS 是如何建⽴连接的?其间交互了什么?

HTTPS 协议是在 HTTP 协议上增加了 TLS 的连接过程,TLS 的连接过程涉及四次通信

  1. Client Hello

    由客户端向服务端发送建立连接请求,向服务端发送以下内容

    • 客户端支持的 SSL/TLS 协议版本
    • 客户端支持的密码套件
    • 客户端产生的随机数(client-random)
  2. Server Hello

    在服务端收到连接请求后,向客户端发送的内容

    • 确认 SSL/TLS 协议版本
    • 确认使用的密码套件
    • 服务端产生的随机数(server-random)
    • 服务端的数字证书
  3. 客户端回应

    客户端收到服务端发送来的数字证书,会向 CA 验证证书的有效性,并从证书中取出服务端的公钥,用服务端的公钥加密报文,向服务端发送:

    • 用公钥加密的一个随机数(pre-master key)
    • 加密算法改变通知
    • 客户端握手结束通知
  4. 服务端回应

    服务端收到客户端发来的内容后,用私钥解密出 pre-master key,此时服务端和客户端各有三个随机数,通过协商的加密算法计算出本次会话的会话密钥,然后向客户端发送:

    • 加密算法改变通知
    • 服务端握手结束通知

到此整个 SSL/TLS 协议握手结束,接下来客户端和服务端使用计算好的会话密钥进行加密通信。

HTTP/1.0、HTTP/1.1、HTTP/2、HTTP/3 演变

HTTP/1.1 使用 TCP 长连接的方式改善了 HTTP/1.0 短连接频繁握手/挥手造成的开销,同时支持了管道传输,可以减少整体响应时间。但 HTTP/1.1 仍存在以下问题:

  • 请求头部冗余
  • 请求在服务端是按顺序执行的,如果某一个请求执行时间过长,客户端会一直收不到相应,就会造成队头阻塞
  • 没有优先级控制
  • 只能由客户端主动发送请求

HTTP/2 相比 HTTP/1.1 做出了一些优化

  • 压缩头部:如果多个请求的头部较为相似,那么会自动帮你消除重复的部分,这部分采用 HPack 算法实现
  • 二进制报文:在 HTTP/1.0 和 HTTP/1.1 中报文都是可读的纯文本,而在 HTTP/2 中采用了二进制格式,减少了收发报文的两端对纯文本的编码过程,提高效率
  • 数据流:在 HTTP/2 中的数据包不是按序发送的,同一个连接里连续的数据包可能不属于同一个请求;同时客户端可以指定数据流的优先级,高优先级的数据流会先被服务端响应
  • 多路复用:移除了 HTTP/1.1 中的串行请求,不会再出现队头阻塞的现象
  • 主动推送:在一定程度上改善了传统的请求-应答工作模式,服务端可以主动推送数据到客户端

在 HTTP/3 中放弃使用 TCP 作为传输层协议,采用了基于 UDP 的 QUIC 作为传输层协议,同时 TLS 版本更新到 1.3,头部压缩算法改为 QPack;最主要的是将因为传输层协议基于 UDP,将以往的 HTTPS 协议的 TCP 三次握手 + TLS 四次握手聚合成了 QUIC 三次握手,大幅提升了请求的连接速度。

TCP 协议

TCP 全称 Transmission Control Protocol,大部分应用使用的传输层协议。TCP 是一个面向连接,可靠的,基于字节流的传输层通信协议。

  • 面向连接:一定是一对一的,且需建立连接才能通信
  • 可靠的:无论链路中发生任何异常,TCP 都可以保证一个报文顺利的到达对端
  • 字节流:无论消息有多大都可以有序的传输,如果出现重复的报文会丢弃

如何唯一确定一个 TCP 连接

通过 TCP 四元祖可以唯一确定一个 TCP 连接

  • 源地址
  • 源端口
  • 目标地址
  • 目标端口

其中源地址和目标地址在 IP 报文头部,作用是寻找主机;源端口和目标端口在 TCP 报文头部,作用是找到目标进程

TCP 的三次握手和四次挥手

三次握手

最开始客户端和服务端都处于 CLOSED 状态,首先服务端监听一个端口,随后进入 LISTEN 状态,等待连接。随后开始三次握手:

  • 第一次握手:客户端向服务端发送一个含有随机序号(client_isn)且 SYN 标志位被置为 1 的报文,随后客户端进入 SYN_SENT 阶段。
  • 第二次握手:服务端收到包含 SYN 标志位的报文后,从中获取客户端发送过来的 client_isn 后,将其 +1,并向客户端发送一个含有服务端随机序号(server_isn)且 SYN/ACK 标志位被置为 1 且确认号为 client_isn + 1 的报文给客户端,并进入 SYN_RCVD 阶段。
  • 第三次握手:客户端收到服务端回复的 SYN/ACK 报文后再向服务端发送一个序号为 client_isn + 1 且 ACK 标识位被置为 1 且确认号为 server_isn + 1 的报文,并进入 ESTABLISHED 阶段

当服务端收到第三次握手的报文后也进入 ESTABLISHED 阶段

注:因为第三次握手时客户端和服务端已经建立连接了,所以第三次握手可以携带数据

四次挥手

参与一条 TCP 连接的两个进程中的任何一个都能终止连接,下面以客户端主动关闭连接为例:

  • 第一次挥手:客户端向服务端发送一个 FIN 标识为被置为 1 的报文,并进入 FIN_WAIT_1 状态
  • 第二次挥手:服务端收到 FIN 报文后,向客户端发送一个 ACK 标识被置为 1 的报文,并进入 CLOSED_WAIT 阶段
  • 第三次挥手:服务端收到 ACK 报文后,向客户端发送一个 FIN 标识为被置为 1 的报文,并进入 LAST_ACK 阶段
  • 第四次挥手:当客户端收到第三次挥手的报文后,向客户端发送一个 ACK 标识被置为 1 的报文,并进入 TIME_WAIT 阶段,随后等待 2MSL 的时间进入 CLOSED 状态

当服务端收到第四次挥手的报文后进入 CLOSED 状态

注:主动关闭连接的一侧才有 TIME_WAIT 阶段

为什么是三次握手

使用三次握手的目的:

  • 避免历史连接初始化连接
  • 同步双方初始化序号
  • 避免浪费资源

如果是两次握手则⽆法防⽌历史连接的建⽴,会造成双⽅资源的浪费,也⽆法可靠的同步双⽅序列号。

如果是四次握手是因为三次握⼿就已经理论上最少可靠连接建⽴,所以不需要使⽤更多的通信次数。

为什么是四次挥手

  • 客户端发送 FIN 报文时,仅代表客户端没有数据要向服务端发送
  • 因为 TCP 是双向连接的,可以互相发送数据。所以当服务端收到 FIN 报文时,此时服务端可能还有数据要发送到客户端,所以先返回 ACK 报文,等所有数据发送结束再向客户端发送 FIN 报文

为什么关闭时需要 2MSL 的延时

MSL 是 Maximum Segment Lifetime 最大报文生存时间,它是任何报文在网络中存在的最长时间,超出此时间的报文都会被丢弃。

2MSL 的合理解释是:⽹络中可能存在来⾃发送⽅的数据包,当这些发送⽅的数据包被接收⽅处理后⼜会向对⽅发送响应,所以⼀来⼀回需要等待 2 倍的时间,⽐如如果被动关闭⽅没有收到断开连接的最后的 ACK 报⽂,就会触发超时重发 FIN 报⽂,另⼀⽅接收到 FIN 后,会重发 ACK 给被动关闭⽅,⼀来⼀去正好 2MSL。

TCP 和 UDP 的区别

TCP 流量控制

如果 TCP 第三次握手的包没收到会怎样