本文共 1857 字,大约阅读时间需要 6 分钟。
分析
TCP状态转移要点
TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。网络服务器程序要同时管理大量连接,所以很有必要保证无用连接完全断开,否则大量僵死的连接会浪费许多服务器资源。在众多TCP状态中,最值得注意的状态有两个:CLOSE_WAIT和TIME_WAIT。1、LISTENING状态
FTP服务启动后首先处于侦听(LISTENING)状态。2、ESTABLISHED状态
ESTABLISHED的意思是建立连接。表示两台机器正在通信。3、CLOSE_WAIT
对方主动关闭连接或者网络异常导致连接中断,这时我方的状态会变成CLOSE_WAIT 此时我方要调用close()来使得连接正确关闭
4、TIME_WAIT
我方主动调用close()断开连接,收到对方确认后状态变为TIME_WAIT。TCP协议规定TIME_WAIT状态会一直持续2MSL(即两倍的分段最大生存期),以此来确保旧的连接状态不会对新连接产生影响。处于TIME_WAIT状态的连接占用的资源不会被内核释放,所以作为服务器,在可能的情况下,尽量不要主动断开连接,以减少TIME_WAIT状态造成的资源浪费。
主动关闭的一方在发送最后一个 ack 后,不会等待被动关闭方任何回应,就会直接进入 TIME_WAIT 状态 停留2MSL(max segment lifetime)时间。这个是TCP/IP必不可少的,也就是“解决”不了的。等待被动关闭方成功收到这个ack此次四次挥手结束。
也就是TCP/IP设计者本来是这么设计的
主要有两个原因 1。防止上一次连接中的包,迷路后重新出现,影响新连接 (经过2MSL,上一次连接中所有的重复包都会消失) 2。可靠的关闭TCP连接 在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发 fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以 主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。TIME_WAIT 并不会占用很大资源的,除非受到攻击。
还有,如果一方 send 或 recv 超时,就会直接进入 CLOSED 状态
不可避免的TIME_WAIT优化方案:
具体操作参考:
**代码层面:**避免频繁的主动开启关闭链接
操作系统层面:
首先,我们要防止不断开辟新的端口,这可以 重用本地地址和端口net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
以前我总是一个端口不行,就换一个新的使用,所以导致让数千个端口进入CLOSE_WAIT状态。如果下次还发生这种尴尬状况,我希望加一个限定,只是当前这个端口处于CLOSE_WAIT状态!
尽快关闭TIME_WAIT的链接
LINGER是“拖延”的意思。net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
默认情况下(Win2k),SO_DONTLINGER套接字选项的是1;SO_LINGER选项是,linger为{l_onoff:0,l_linger:0}。
排查步骤
查看TCP连接状态
netstat -ant
查看每个进程的
netstat -nap | grep 7038
netstat -an|awk '/tcp/ {print $6}'|sort|uniq -c
16 CLOSING130 ESTABLISHED298 FIN_WAIT1 13 FIN_WAIT2 9 LAST_ACK 7 LISTEN103 SYN_RECV
5204 TIME_WAIT
状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
转载地址:https://blog.csdn.net/yangshengwei230612/article/details/115165095 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!