计算机网络核心知识--1.3 TCP的四次挥手

“挥手”是为了终止连接。
TCP四次挥手的流程图如下:
在这里插入图片描述
第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态;
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态;
第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACL状态;
第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

在TCP的四次挥手的状态途中,有一个超时设置,这个超时设置是2MSL,那为什么需要等待这段时间呢?为什么不直接转换为closed状态?
主要有两个原因:
1,TIME-WAIT状态是用来保证有足够的时间让对端收到ACK,如果被动关闭的那方没有收到ACK,就会触发被动端重发FIN包,一来一去正好是两个MSL;
2,就是有足够的时间让这个连接不会和后面的连接混在一起。因为有些路由器会缓存IP数据包,如果连接被重用了,那么这些延迟收到的包就有可能跟新连接混在一起。

为什么需要四次挥手才能中断连接呢?
前面说过,全双工的意思是允许数据在两个方向上同时传输,即在同一时间,服务器可以发送数据给客户端,客户端也可以发送数据给服务器,而因为TCP是全双工的,所以发送方和接收方都需要FIN报文ACK报文,也就是说发送方和接收方各自需要两次挥手即可,只不过有一方是被动的,所以看上去就成了四次挥手。

Linux服务器频繁出现大量CLOSE_WAIT的原因?
服务器保持大量的CLOSE_WAIT,只有一种情况,就是,在对方发送一个FIN报文之后,程序这边没有进一步发送ACK,或者FIN报文,换句话说,就是在对方关闭连接后,程序没有检测到,或者程序本身就已经忘了这个时候需要关闭连接,于是这个资源就一直被程序占用着。遇到这种情况,多半是程序里有bug,通常是某些连接没有及时释放导致的,或者是某些配置,例如线程池中的线程数配置不合理,此时就需要我们结合具体的业务去排查了。

该命令主要是获取当前服务器处于各个状态下的连接数:

netstat -n | awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}'

在这里插入图片描述
一旦CLOSE_WAIT很多,比如说有几千的话,就需要我们去排查问题了,因为对于Linux服务器来说,会为每个用户分配有限的文件句柄数,而我们的连接也是和文件句柄一一对应的。如果CLOSE_WAIT状态一直被保持,那么意味着对应数目的通道一直被占用着,一旦达到了上限,则新的请求就无法被处理,接着就是“too many open files”异常,紧接着有可能造成软件服务器的奔溃。

猜你喜欢

转载自blog.csdn.net/tanwenfang/article/details/89306637
今日推荐