TCP四次挥手及相关

断开过程

  1. 假设客户端准备关闭连接,会发送一个TCP首部FIN置1的报文,即FIN报文给服务器,然后客户端进入FIN_WAIT_1状态;

  2. 服务端收到报文后,会向客户端发送一个ACK应答报文,然后服务端进入CLOSED_WAIT状态;

  3. 客户端收到来自服务端的ACK报文后,进入FIN_WAIT_2状态;

  4. 等待服务器处理完数据后,也向客户端发送FIN报文,之后服务器进入LAST_ACK状态;

  5. 客户端收到来自服务器的FIN报文后,就向服务器发送ACK报文,之后进入TIME_WAIT状态;

  6. 服务器收到客户端发来的ACK报文后,进入CLOSED状态,至此服务器已完成连接的关闭;

  7. 客户端在经过2MSL(Maximum Segment Lifetime,报文最大生存时间)的时间后,进入CLOSED状态,至此客户端完成连接的断开。

为什么是四次挥手?

关闭连接时,客户端发送FIN报文,表示其不再发送数据,但还可以接收数据服务端在收到客户端的FIN报文后,先回一个ACK报文,然后等待完成数据的发送和处理,再发送FIN报文,所以比三次握手导致多了一次。

四次挥手分别丢失后会发生什么?

第一次挥手丢失:客户端发送FIN报文丢失,迟迟收不到来自服务器的ACK报文,会触发超时重传机制,重新发送FIN报文,超过一定次数客户端直接进入CLOSED状态;

第二次挥手丢失:由于ACK报文是不会重传的,所以如果第二次挥手丢失,客户端迟迟收不到来自服务器的ACK报文就会触发超时重传机制,重新发送FIN报文,超过一定次数后直接进入CLOSED状态;

在第二次挥手后,客户端收到服务器的ACK报文后,进入FIN_WAIT_2状态,对于close函数关闭的连接,由于无法再发送和接收数据,这个状态不能持续太久,一旦超过时长还没有收到来自服务器的FIN报文,就会自动进入CLOSED状态;如果是客户端使用shutdown函数发起断开连接,且指定关闭发送方向,这种情况下客户端会一直保持FIN_WAIT_2状态直到第三次挥手。

第三次挥手丢失:服务器收到客户端的FIN报文后,内核会自动回复ACK报文,进入CLOSE_WAIT状态,调用close函数发起关闭连接,内核发送FIN报文给客户端,如果这个报文丢失,服务器迟迟收不到来自客户端的ACK报文,就会触发超时重传机制,服务器会重发FIN报文,且超过一定次数服务器自动进入CLOSED状态;

第四次挥手丢失:客户端收到FIN报文后,进入TIME_WAIT状态,并回复ACK报文给服务器,若该报文丢失,服务器迟迟没有收到

ACK报文就会触发超时重传机制,重新发送FIN报文,超过次数直接进入CLOSED状态。

TIME_WAIT等待时间为什么是2MSL?

网络中可能存在发送方的数据包,当这些数据包被接收方处理后又会向对方发送响应,一来一回需要等待2MSL的时间。这个时间是从客户端接收到服务器的FIN报文后内核发送ACK报文开始计时的,如果在这个时间内,客户端又收到了服务器重发
的FIN报文,则重新计时。

为什么需要TIME_WAIT状态?

为了防止历史连接中的数据,被后面出现的相同四元组四元组「源 IP、源端口、目的 IP、目的端口」 的连接错误的接收,2MSL的时长足以保证两个方向上的数据包都被丢弃,使得原来连接上的数据包在网络中都自然消失,新出现的数据包一定是新连接产生的;

保证被动关闭连接(此处是服务器)的一方,可以正确的关闭连接。如果第四次挥手丢失了,服务器会重发FIN报文,TIME_WAIT状态可以保证等待足够的时间来确保最后的ACK报文能让服务器接收。

TIME_WAIT过多有什么危害?

会占用内存资源,占用端口资源。如果发起连接一方的TIME_WAIT状态过多,占满了端口资源,会导致无法创建新的连接。

 

posted @   unclejac  阅读(257)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示