计算机网络复习------TCP的四次挥手

断开一个TCP连接时,需要客户端和服务器端总共发出4个包,以确认连接的断开。

在Socket编程中,这过程由客户端或服务端任一方,执行Close来触发。

"挥手"是为了终止连接,TCP四次挥手的流程图如下

上图由客户端主动触发close。数据传送完毕之后,双方都可以释放连接,最开始的时候客户端和服务端都处于ESTABLISHED状态。然后客户端主动关闭,服务器被动关闭。

第一次挥手

首先客户端进程发出连接释放报文(FIN),并且停止发送数据。在该数据报的报头中,TCP Flags 中的 FIN = 1,假设客户端定义的序列号为seq=u,该值等于前面ESTABLISHED状态数据最后一次发送的时候,已经传送过来的数据的最后一个字节的序号加上1。此时客户端就进入了FINWAIT1,这个终止等待1的状态。TCP规定即使FIN不携带数据,也要消耗掉一个序号。即回值的时候u要加上1。

第二次挥手

当服务器收到连接释放报文之后,也要发出确认报文,即ACK=1。作为回应akc=u+1,并且也带上了自己的序列号seq=v。此时服务端就进入了CLOSEWAIT,关闭等待的状态。TCP服务器通知高层的进程,客服端要释放与服务器之间的连接,这时候会处于半关闭的状态,即客户端没有数据要发送了,但是服务器要发送数据,客户端还是能够接受的。CLOSEWAIT状态还要持续一段时间。

第三次挥手

客户端收到服务器的确认请求之后,客户端就进入了FIN_WAIT_2,即终止等待2状态。等待服务器发送释放连接报文,也就是第三次挥手的请求。因此在这个时间内还需要接收服务器发送最后的数据,服务器将最后的数据发送完毕后就会向客户端发送连接释放报文,FIN=1,ack=u+1。有可能在半关闭的状态,服务器很可能又发送了一些数据,假定此时的序号变为了w。此时服务器就进入到了LAST_ACK的状态。等待客户端的最终确认。

第四次挥手

客户端在收到服务器的连接释放报文之后,必须发出确认,即ACK=1,然后再将服务器发送过来的w变成w+1,回发给服务器。

此时的seq为u+1。此时客户端就进入了TIME_WAIT,即时间等待的状态,这时客户端的TCP连接还没有释放,必须经过2MSL时间后,连接才会真正的释放,才会进入到CLOSED状态。MSL最长报文段生命。在Linux MSL 为30s,而服务器只要收到客户端发出的确认,立即就进入CLOSED状态。

由图可知,服务器结束TCP的连接时间,要比客户端,稍早一些。

总结

TCP采用四次挥手来释放连接

第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据,Client进入FIN_WAIT_1状态;

第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入LAST_ACK状态;

第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态;

第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

 

为什么会有TIME_WAIT状态?

确保由足够的时间让对方收到ACK

TIME_WAIT状态用来保证有足够的时间让对端接收完ACK,如果被动关闭的那方没有收到ACK就会触发被动端重发FIN包,一来一去正好是2MSL。

避免新旧连接混淆

有足够的时间让这个连接,不会跟后面的连接混在一起,因为有些路由器会缓存IP数据包。如果连接被重用了,那么这些延迟被收到的包就有可能跟新连接混在一起

 

为什么需要四次挥手才能断开连接?

全双通的意思是允许数据在两个方向上同时传输,即在同一时间,服务器可以发送数据给客户端,客户端也可以发送数据给服务器。

因为全双工,发送方和接收方都需要FIN报文和ACK报文

发送方和接收方各只需两两次挥手即可,只不过有一方是被动的,所以看上去就成了四次挥手

 

服务器出现CLOSE_WAIT状态的原因

问题其中一个表现是客户端一直在请求,但是返回给客户端的信息是异常的。服务端压根也没收到请求。

服务器保持大量的CLOSE_WAIT只有一种情况,那就是在对方发送一个FIN报文之后,程序这边没有进一步发送ACK,或者FIN报文以确认。

对方关闭Socket连接,我方忙于读或写,没有及时关闭连接

对方关闭连接后,程序里没有检测到,或者程序本身就已经忘了这个时候需要关闭连接,于是这个资源就被程序占用着。

遇到这种情况多数是程序里面有BUG,通常是有些连接没有释放

检查代码,特别是释放资源代码

或者某些配置,如线程池中的线程数配置不合理

检查配置,特别是处理请求的线程配置

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值