TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层协议。在建立连接和断开连接时,TCP 使用三次握手和四次挥手来确保通信的可靠性和正确性。

三次握手与四次挥手

三次握手过程

  1. 客户端向服务器发送连接请求: 客户端发送一个 SYN(同步)标志位被置为 1 的数据包给服务器,并指定初始序列号(Seq=X)。
  2. 服务器响应确认请求: 服务器收到 SYN 包后,如果同意连接,会发送一个 ACK(确认)标志位和 SYN 标志位都被置为 1 的数据包给客户端,表示确认收到请求,并分配自己的序列号(Seq=Y),同时也会回复一个确认序号(Ack=X+1),表示收到的请求已确认。
  3. 客户端发送确认响应: 客户端收到服务器的确认后,也会向服务器发送一个 ACK 标志位被置为 1 的数据包,表示对服务器的响应已确认,同时也会回复一个确认序号(Ack=Y+1),表示收到的响应已确认。
    这样,客户端与服务器之间的连接就建立起来了,可以开始进行数据的传输。

四次挥手过程

  1. 客户端发送断开连接请求: 客户端发送一个 FIN(结束)标志位被置为 1 的数据包给服务器,表示客户端不再发送数据。
  2. 服务器确认断开连接请求: 服务器收到客户端的 FIN 包后,会向客户端发送一个 ACK 标志位被置为 1 的数据包,表示收到了客户端的断开请求。
  3. 服务器向客户端发送断开连接请求: 当服务器不再发送数据时,会向客户端发送一个 FIN 标志位被置为 1 的数据包,表示服务器准备好断开连接。
  4. 客户端确认断开连接请求: 客户端收到服务器的 FIN 包后,会向服务器发送一个 ACK 标志位被置为 1 的数据包,表示确认收到服务器的断开请求。
    当客户端收到确认后,等待一段时间(TIME_WAIT 状态,2MSL),确保服务器接收到确认信息,然后关闭连接。服务器在接收到客户端的确认后,也会关闭连接。这样,客户端与服务器之间的连接就断开了。

三次握手状态转变

客户端

  1. CLOSED:初始状态,表示连接未建立。
  2. SYN_SENT:发送了SYN包后进入此状态,等待服务器的确认。
  3. ESTABLISHED:收到服务器的确认后进入此状态,连接建立成功。

服务器端

  1. CLOSED:初始状态,表示连接未建立。
  2. LISTEN:准备接受连接请求,等待客户端发送SYN包。
  3. SYN_RCVD:收到客户端的SYN包后进入此状态,发送确认和自己的SYN包。
  4. ESTABLISHED:收到客户端的确认后进入此状态,连接建立成功。

四次挥手状态转变

客户端

  1. ESTABLISHED:初始状态,表示连接正常进行。
  2. FIN_WAIT_1:发送了FIN包后进入此状态,等待服务器的确认。
  3. FIN_WAIT_2:收到服务器的确认后进入此状态,等待服务器的FIN包或超时。
  4. TIME_WAIT:收到服务器的FIN包后进入此状态,等待服务器的确认或超时。
  5. CLOSED:收到服务器的确认后进入此状态,连接关闭。

服务器端

  1. ESTABLISHED:初始状态,表示连接正常进行。
  2. CLOSE_WAIT:收到客户端的FIN包后进入此状态,发送确认。
  3. LAST_ACK:发送了自己的FIN包后进入此状态,等待客户端的确认。
  4. CLOSED:收到客户端的确认后进入此状态,连接关闭。

图解

图片损坏

为什么是三次握手

分析

  1. “握手”也就是客户端和服务器端进行数据通信的过程是需要资源的,而且由于TCP是通信的基础,因此在真实的网络请求中建立连接的次数是非常多的,因此需要尽可能地找到最小的“握手”次数来保证连接的稳定性
  2. 很显然,通过四次握手必然能够实现稳定的连接(双方能够互相发送消息),并且这种连接是具有实时性的,不会因为网络通信问题导致两端的连接状态不一致
  3. 现在的问题是能否将四次握手简化至三次甚至两次?如果简化至两次,考虑一种情况,如果只有两次握手,即客户端发送连接请求,服务器接受连接请求并发送确认,连接就建立成功了。但是,如果这个确认包由于某些原因在网络中被延迟,而客户端已经认为连接已经建立成功,那么客户端就会开始发送数据了。然而,服务器并不知道客户端已经开始发送数据,因为它从未收到客户端的确认,所以也不会发送数据的确认。这样就可能导致两边的连接状态不一致,客户端认为连接已建立,而服务器并不知情。当最终确认包到达服务器时,服务器可能会误解为这是一个新的连接请求,从而建立了一个新的连接。这就会导致两个问题:一是旧的连接处于半开状态,消耗了服务器的资源;二是客户端发送的数据在新连接上丢失,因为服务器并不知道它已经发送了数据。
  4. 综上分析:三次握手是消耗资源最少的能够保证有效连接以及确保连接时效性的最佳连接确认方式

三次握手的作用

  1. 初始化序列号:在通信开始之前,需要确定初始的序列号以及确认号。这两个序列号是 TCP 进行数据传输的基础。通过三次握手,客户端和服务器可以相互交换初始的序列号,从而确保后续的数据传输能够正确地同步。
  2. 确认双方的发送和接收能力:通过三次握手,客户端和服务器可以确认对方的发送和接收能力正常。在第三次握手中,服务器发送确认消息,客户端接收并发送确认消息,这样双方就可以确认彼此的能力,以及连接是否能够正常建立。
  3. 防止旧连接的影响:在网络中,可能会存在旧的连接或者延迟的数据包。通过三次握手,可以确保只有最新的连接才能够建立,避免了旧连接对新连接的影响。
  4. 防止重复的连接请求:如果没有三次握手,客户端可能会发送多个连接请求,导致服务器建立多个连接。通过三次握手,可以防止重复的连接请求,确保只有一条连接被正确地建立。

补充

MSL

  1. MSL(Maximum Segment Lifetime,最大报文生存时间)是 TCP 协议中的一个概念,指的是 TCP 报文在网络中允许存在的最长时间。
  2. MSL 的值通常由实现 TCP 协议的操作系统决定,一般为 2 分钟(120 秒)。
  3. MSL 的主要作用是确保网络中的旧数据报文能够及时丢弃,以避免旧的报文在网络中产生混乱。当一个 TCP 连接被关闭时,连接的每一端都会在关闭之后等待 MSL 的时间,以确保连接中的所有数据报文都已经在网络中完全传输并被丢弃。这样可以确保网络中不会再出现与旧连接相关的数据报文,避免对新连接的影响。
    四次挥手时为什么要等2MSL
  4. 保证A发送的最后一个ACK报文段一定能被B接收到
  5. 防止已失效的连接请求报文段重新出现在新的连接中(使本次请求产生的所有数据都消失在网络中)