三次握手

  • 通过传输层的 tcp 协议建立网络连接时,走三次报文握手过程(总体上其实就是一次 tcp 握手)
  1. 一开始客户端和服务端都处于 CLOSE 状态
  2. 客户端发送一个 请求报文
    1. SNY=1, seq = x
      1. SYN=1 表示 tcp 标头中 SYN 位有效,表示当前为握手信号
      2. seq=x 表示当前请求的序列号为 x
    2. 然后客户端会处于 SYN-SENT 状态
  3. 服务端监听时,如果收到客户端的请求报文,会返回一个响应报文
    1. SYN=1 ACK=1 seq=y ack=x+1
      1. SYN=1 表示 tcp 标头 SYN 位有效,表示当前为握手信号
      2. ACK=1 表示 tcp 标头 ACK 位有效,表示当前为响应信号
      3. seq=y 表示当前响应报文的序列号为 y
      4. ack=x+1 在 ACK 位有效的前提下,表示当前请求是响应序列号为x的请求(针对要响应的请求的seq的值)
    2. 服务端会处于 SYN-RCVD 状态
  4. 客户端收到服务端的确认报文后,会再次发送一个确认收到服务端确认报文的报文
    1. ACK=1 seq=x+1 ack=y+1
      1. ACK=1 表示 tcp 标头 ACK 位有效,表示当前为响应信号
      2. seq=x+1 表示当前响应报文的序列号为x+1,是上一次握手信号的序列号+1
      3. ack=y+1 在 ACK 位有效的前提下,表示当前请求是响应序列号为y的请求(针对要请求的seq的值)
    2. 客户端会处于 ESTAB-LISHED 状态
  5. 服务端收到客户端的确认报文,会处于 ESTAB-LISHED 状态

image.png

为什么不是两次?

  1. 如果客户端第一次发送连接请求报文,由于网络延迟,未能及时到达服务端
  2. 那么客户端会重新发多一次请求报文
  3. 此时第二次请求报文服务端进行了响应,服务端分配了资源等,和客户端开始进行数据交互
  4. 假设此时客户端第一次发送的请求报文又到了服务端
  5. 服务端同样对该报文进行响应,并且会分配资源,等待和客户端进行交互
    1. 但是这次不会有数据交汇,会白白兰浪费服务端的资源
  6. 如果是三次握手,那么第一次请求报文的响应报文到达客户端时客户端发现根本不对,就会发送个复位的报文过去,让服务器撤销开辟的资源

四次挥手

  1. 客户端会发送一条客户端向服务端的结束连接信号
    1. FIN=1,表示 tcp 标头 FIN 位有效,表示当前请求是结束连接信号
  2. 在客户端收到服务端的响应后,此时客户端向服务端的单向数据通信结束
    1. 但是服务端可能还有一些数据需要继续发给客户端,所以不会断开
  3. 服务端完成剩余的客户端数据交互后,会发送一个服务端向客户端的结束连接信号
    1. 为啥 seq不是v+1呢? 因为在 CLOSE-WAIT 阶段可能会传输数据,所以数据不会连续
    2. 该结束信号是针对客户端发起的结束连接信号,所以 ack 还是 u+1
  4. 服务端收到客户端的响应后,此时服务端向客户端的单向数据通信结束
    1. 明明上面说客户端向服务端的单向数据通信结束,客户端咋还能进行响应?
      1. 确认报文的报文段是不可以携带任何数据的,但是需要消耗序列号
      2. 可以看成不是一条数据通信

        image.png

为啥要有 TIME-WAIT

  • 可能服务端发送的结束报文由于网络延迟客户端未能收到或者丢失,导致客户端没有响应服务端的结束报文
    • 服务端会重新发送一条结束报文
    • TIME-WAIT 阶段就是等待这个可能会发送的结束报文