tcp连接的TIME_WAIT和CLOSE_WAIT

TCP四次挥手

在tcp连接断开的过程中都会产生很多中间状态,而TIME_WAIT以及CLOSE_WAIT就是其中最常见的两种.

四次挥手

TIME_WAIT并不可怕,CLOSE_WAIT才可怕,因为CLOSE_WAIT很多,表示说要么是你的应用程序写的有问题,没有合适的关闭socket;要么是说,你的服务器CPU处理不过来(CPU太忙)或者你的应用程序一直睡眠到其它地方(锁,或者文件I/O等等),你的应用程序获得不到合适的调度时间,造成你的程序没法真正的执行close操作。

TIME_WAIT

这里的TIME_WAIT状态主要有两个作用

  1. 确保连接方能在设置的时间范围内,关闭自己的连接。
    在上图中,Client收到Server的Fin N以后,会把自己置为TIME_WAIT状态,然后给Server发送一个ack,但是由于网络延迟网络拥塞等不稳定的网络状况,Client的ack服务器可能并未收到,那么Server会重发一个FIN,Client需要保持TIME_WAIT状态以便再次发出ack.
  2. 防止前一个连接上延迟的数据包或者丢失重传的数据报,被后面复用的连接错误接受
    如果没有TIME_WAIT,那么当这个连接关闭以后,恰好新建立的连接的五元组(源IP:PORT TCP 目的IP:PORT)是一样的,那么前一个的延迟和重传数据包就会发到新的连接上取,如果恰好序列号也是对应的,那么这个数据可能会被'正确'的接收

虽然TIME_WAIT是必要的,但是大量出现的TIME_WAIT必然会影响系统的性能。虽说TIME_WAIT保持了设置的时间以后会自动退出这个状态,但是在一些特殊场景下,这个时间段内的TIME_WAIT大量增多还是会造成影响。

处理TIME_WAIT

解决思路很简单,就是让服务器能够快速回收重用那些TIME_WAIT的资源。
编辑/etc/sysctl.conf

net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间。

CLOSE_WAIT

如果出现CLOSE_WAIT那么问题一般都是出在自己这一方,而且大概率与操作系统内核无关,是自己程序的问题。
而且这个问题一般都是未正确调用相应的close方法

可能的原因一般都是,服务端在进行耗时较久的操作,客户端检测连接超时主动发起关闭,而此时服务端无法回复或主动发起FIN,当服务端操作完成以后,客户端的可能由于超时已经移除这个连接了,此时服务端再次发送FIN,客户端也不会正确的响应。

你可能感兴趣的:(tcp连接的TIME_WAIT和CLOSE_WAIT)