原创

TCP协议四次挥手解析

1.TCP 四次挥手流程

TCP四次挥手流程
TCP四次挥手流程
  • 第一次分手: 主机 1(可以是客户端,也可以是服务器端),设置 Sequence Number,向主机 2 发送一个 FIN 报文段;此时,主机 1 进入 FIN_WAIT_1 状态;这表示主机 1 没有数据要发送给主机 2 了;
  • 第二次分手: 主机 2 收到了主机 1 发送的 FIN 报文段,向主机 1 回一个 ACK 报文段,Acknowledgment Number 为 Sequence Number 加 1;主机 1 进入 FIN_WAIT_2 状态;主机 2 告诉主机 1,我“同意”你的关闭请求;
  • 第三次分手: 主机 2 向主机 1 发送 FIN 报文段,请求关闭连接,同时主机 2 进入 LAST_ACK 状态;
  • 第四次分手: 主机 1 收到主机 2 发送的 FIN 报文段,向主机 2 发送 ACK 报文段,然后主机 1 进入 TIME_WAIT 状态;主机 2 收到主机 1 的 ACK 报文段以后,就关闭连接;此时,主机 1 等待 2MSL 后依然没有收到回复,则证明 Server 端已正常关闭,那好,主机 1 也可以关闭连接了。

2.Wireshark 抓取 TCP 连接和挥手数据包

Wireshark抓取TCP连接和挥手数据包 问题来了,我用 wireShark 抓了一个包,结果显示三次挥手就 GG 了?然后翻阅各种资料,有人说不可能,更有人肯定的答复必须四次挥手,可能是被网上的博客洗脑了。事实胜于雄辩,最后我终于找到一个可靠的答复,如下: 如果在客户端关闭后,服务端无任何操作也是直接关闭,则服务端会将四次挥手第二三次挥手合并为 1 个报文,也就是 FIN+ACK,捎带 ACK 机制,如果是半连接状态,则会使用四次挥手,或者如果服务端没有立即关闭通道,而是做了其它的操作,再关闭,则也是四次挥手。看了 LWIP 的 TCP/IP 协议栈实现源码,确实是这样操作的,客户端有一种情况直接从 FIN_WAIT_1 到 TIME_WAIT 状态,服务端也有一种是从 CLOSE_WAIT 到 LAST_ACK 状态是在一个通信报文段实现的,也就是正常情况下 CLOSE_WAIT 到 LAST_ACK 需要发送两段报文,但是在三次挥手的情况下,只发送一段报文就可以了。所以在客户端关闭后,服务端无任何操作立即关闭的情况下,只需要三次挥手即可,减少一次通信。

3.为什么要四次分手?

  • TCP 协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。
  • TCP 是全双工模式,这就意味着,当主机 1 发出 FIN 报文段时,只是表示主机 1 已经没有数据要发送了,主机 1 告诉主机 2,它的数据已经全部发送完毕了;
  • 但是,这个时候主机 1 还是可以接受来自主机 2 的数据;
  • 当主机 2 返回 ACK 报文段时,表示它已经知道主机 1 没有数据发送了,但是主机 2 还是可以发送数据到主机 1 的;
  • 当主机 2 也发送了 FIN 报文段时,这个时候就表示主机 2 也没有数据要发送了,就会告诉主机 1,我也没有数据要发送了,之后彼此就会愉快的中断这次 TCP 连接。

4.客户机为什么要等待 2MSL 时间?

  • ① 为了保证服务器能够收到客户机发送的最后一个确认报文。 因为这个最后报文可能丢失,服务器收不到客户机的确认信息,就无法进入 CLOSED 状态。就会在重传定时器到达后重新发送上一次的报文(此时会重置时间等待计时器,再次等待 2MSL 时间),这样客户机在等待 2MSL 时间过程中就可以收到这个重传报文,并重新发送确认报文。
  • ② 防止出现“已失效的连接请求报文”再次出现的情况。 客户机在等待的这 2MSL 时间中,就可以使此次连接的所有报文都从网络中消失,这样在下一次新的连接中就不会出现旧的连接请求报文。

    MSL:(Maximum Segment Lifetime)报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。

正文到此结束