《TCP三次捂手、四次挥手和状态转换详解》

前言: 本文将讲解TCP三次捂手建立连接,到四次挥手断开连接的过程,并且配合TCP状态转换图解释。解释SYN 、seq 、ack、FIN的含义和关系。建议读者先理解三捂和四挥后在结合状态转换图看,网络编程面试经常会问道这个问题,建议读者弄懂。

TCP三次捂手和四次挥手

《TCP三次捂手、四次挥手和状态转换详解》

名词解释

  • SYN: 请求建立连接
  • FIN:请求断开连接
  • seq:***,如果是第一次发送,这个自己随机产生,否则,在上一次基础上 + 1。
  • ack:确认号,确认***是对方发送*** + 1,可以用来确认自己应答的是那个***的报文。
  • ESTABLISHED:此状态表示已经建立连接,建立连接后的每次通信ACK都是client三次捂手最后发给server的确认号,直到FIN后。
  • TIME_WAIT:也成为2MSL等待状态,RFC 793 [Postel 1981c] 指出MSL为2分钟。然而,实现中的常用值是30s,60s,2min。

TCP状态转换图

《TCP三次捂手、四次挥手和状态转换详解》

名词解释

一、下面是 TCP 三次握手过程的状态变迁。请结合第一张三次握手过程图理解:

  1. CLOSED: 起始点,在超时或者连接关闭时候进入此状态,这并不是一个真正的状态,而是这个状态图的假想起点和终点。
  2. LISTEN: 服务器端等待连接的状态。服务器经过 socket,bind,listen
    函数之后进入此状态,开始监听客户端发过来的连接请求。此称为应用程序被动打开(等到客户端连接请求)。
  3. SYN_SENT: 第一次握手发生阶段,客户端发起连接。客户端调用 connect,发送 SYN 给服务器端,然后进入 SYN_SENT
    状态,等待服务器端确认(三次握手中的第二个报文)。如果服务器端不能连接,则直接进入CLOSED状态。
  4. SYN_RCVD: 第二次握手发生阶段,跟 3 对应,这里是服务器端接收到了客户端的 SYN,此时服务器由 LISTEN 进入
    SYN_RCVD状态,同时服务器端回应一个 ACK,然后再发送一个 SYN 即 SYN+ACK
    给客户端。状态图中还描绘了这样一种情况,当客户端在发送 SYN 的同时也收到服务器端的
    SYN请求,即两个同时发起连接请求,那么客户端就会从 SYN_SENT 转换到 SYN_REVD 状态。
  5. ESTABLISHED: 第三次握手发生阶段,客户端接收到服务器端的 ACK 包(ACK,SYN)之后,也会发送一个 ACK
    确认包,客户端进入 ESTABLISHED 状态,表明客户端这边已经准备好,但TCP
    需要两端都准备好才可以进行数据传输。服务器端收到客户端的 ACK 之后会从 SYN_RCVD 状态转移到 ESTABLISHED
    状态,表明服务器端也准备好进行数据传输了。这样客户端和服务器端都是 ESTABLISHED 状态,就可以进行后面的数据传输了。
    所以ESTABLISHED 也可以说是一个数据传送状态。

二、下面看看TCP断开ESTABLISHED的状态变迁

被动断开,即服务器主动发送FIN断开连接状态变迁如下:

  1. CLOSE_WAIT: 接收到服务器主动发送FIN之后,被动关闭的一方进入此状态。具体动作是接收到 FIN,同时发送 ACK。之所以叫 CLOSE_WAIT可以理解为被动关闭的一方此时正在等待上层应用程序发出关闭连接指令。前面已经说过,TCP关闭是全双工过程,这里客户端执行了主动关闭,被动方服务器端接收到FIN后也需要调用 close 关闭,这个 CLOSE_WAIT 就是处于这个状态,等待发送 FIN,发送了FIN 则进入 LAST_ACK状态。
  2. LAST_ACK: 被动方(服务器端)发起关闭请求,由状态2 进入此状态,具体动作是发送 FIN给对方,同时在接收到ACK 时进入CLOSED状态。

三、主动断开客户端主动发送FIN,即 TCP四次挥手过程的状态变迁:

  1. FIN_WAIT_1: 第一次挥手。主动关闭的一方(执行主动关闭的一方既可以是客户端,也可以是服务器端,这里以客户端执行主动关闭为例),终止连接时,发送 FIN
    给对方,然后等待对方返回 ACK 。调用 close() 第一次挥手就进入此状态。

  2. FIN_WAIT_2: 主动端(这里是客户端)先执行主动关闭发送FIN,然后接收到被动方返回的 ACK 后进入此状态。

  3. CLOSING: 两边同时发起关闭请求时(即主动方发送FIN,等待被动方返回ACK,同时被动方也发送了FIN,主动方接收到了FIN之后,发送ACK给被动方),主动方会由FIN_WAIT_1
    进入此状态,等待被动方返回ACK。

  4. TIME_WAIT: 从状态变迁图会看到,四次挥手操作最后都会经过这样一个状态然后进入CLOSED状态。共有三个状态会进入该状态 由CLOSING进入:同时发起关闭情况下,当主动端接收到ACK后,进入此状态,实际上这里的同时是这样的情况:客户端发起关闭请求,发送FIN之后等待服务器端回应ACK,但此时服务器端同时也发起关闭请求,也发送了FIN,并且被客户端先于ACK接收到。
    由FIN_WAIT_1进入:发起关闭后,发送了FIN,等待ACK的时候,正好被动方(服务器端)也发起关闭请求,发送了FIN,这时客户端接收到了先前ACK,也收到了对方的FIN,然后发送ACK(对对方FIN的回应),与CLOSING进入的状态不同的是接收到FIN和ACK的先后顺序,由FIN_WAIT_2进入:这是不同时的情况,主动方在完成自身发起的主动关闭请求后,接收到了对方发送过来的FIN,然后回应
    ACK。

TIME_WAIT存在的两个理由

  • 可靠地实现TCP全双工连接的终止;
  • 我们知道tcp是有超时重发机制的,TIME_WAIT允许老的重复分节(数据报)在网络中消逝。

禁止转载,拷贝请标明图片出处。
参考:https://blog.****.net/wenqian1991/article/details/40110703