赞
踩
(1)存在TIME_WAIT状态的原因
首先,只有主动调用closed的一方才会在接收到对端的ACK后进入time_wait状态;并且任意一方都可以先发起closed;下图为四次挥手状态:
解析:假设场景为客户端主动向服务器发起断开连接,假如在主动方(客户端)最后一次发送的ACK在网络中丢失,根据TCP的超时重传机制,被动方(服务器)需要重新向客户端发送FIN+ACK,在FIN未达到之前,必须维护这条连接;并且要接收到客户端发出的ACK确认后才能终止连接;如果直接在重传的FIN到达之前而关闭连接,当FIN到达后会促使客户端TCP传输层发送RST重新建立连接,而本质上这是一个正常断开连接的过程。
另一种解释是:
4次握手的最后一个ACK是是由主动关闭方发送出去的,若这个ACK丢失,被动关闭方会再次发一个FIN过来;若主动关闭方能够保持一个2MSL的TIME_WAIT状态,则有更大的机会让丢失的ACK被再次发送出去。
解析:假设没有time_wait状态时,A刚刚与B断开连接,C又以和A相同的ip和port和B建立起连接,TCP协议栈无法区分A和C是不同的连接, 这时,A连接发送的数据到达B之后会被B的TCP传输层当做当下正常的连接发来的数据进行处理,实际上这时上一条连接的脏数据;所以在time_wait等待2MSL(报文在网络最大生存时间),将此连接的数据全部收到并丢弃,才能保证这些数据不会造成错误;
为什么是两个2MSL的原因:如果不到2MSL就断开连接,新连接又以旧连接相同的端口和ip连接服务器,就连接的重复数据报到达又会干扰第二个连接;
(2)TIME_WAIT状态过多有何危害?如何解决TIME_WAIT过多情况?
第一种:首先服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场景就是,如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态;
情景分析案例:
在服务器端值负责接收连接和和接受客户端的数据,在客户端,每创建一个连接就就往服务器发送两次数据,然后close关闭连接,那么客户端必定处理TIME_WAIT状态,如果再次启动客户端,客户端想继续使用同一个本地端口号,那么这个时候就需要使用SO_REUSEADDR进行设置;假如第一次创建的套接字对四元组为(cli:192.168.3.105:5678,server:192.168.3.108:8888),那么程序退出后5678处于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 = 30 //表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
注意:reuse是表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连接; recyse是加速TIME-WAIT sockets回收
(3)如果修改修改time_wait的时间有什么影响?
如果修改time_wait的时间会造成上一个连接的数据没有完全接收到,会重建连接错误;另一个是造成新建的连接出现错误,收到不期望收到的数据;
注意:Linux是无法修改tcp的time_wait值的;
(4)netstat 命令的使用
time_wait:
FIN_WAIT 1:
FIN_WAIT 2:
ESTABLISHED
SYN_RECV:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。