首先简单介绍一下Time_Wait是个什么鬼:
在TCP/IP协议中,我们都知道有三次握手四次挥手的过程,先来一个简单的图:
各个状态和基本的过程想必了解过TCP/IP协议的人都清楚,本次介绍的主题只有Time_Wait状态。(Ps:本文统一将主动断开连接方称A,被动断开连接方称B)
1,Time_Wait状态是什么结点产生的?
在A发送Fin被B接收到,B会发送ACK紧接着发送Fin以后,A接收到另一方发过来的Fin信号,就会将自身的状态设置为Time_Wait状态,并返回一个ACK。
2,为什么需要有一个Time_Wait状态?
主要有两个原因:⑴ 可靠地实现TCL全双工连接的终止;⑵允许老的重复分节在网络中消逝。
3,分别解释一下上述两种具体的实现过程?
⑴ A发送最后一次ACK后,会处于Time_Wait状态下,此时并没有断开连接,若最后一次ACK没有正常发送给B,则B检测超时后会再次发送确认的Fin,此时A处于Time_Wait状态就能正常接收并再次发送确认ACK,以确保服务器能正常断开连接。Time_Wait(2MSL)时间超时后,A端就会自动关闭端口。
⑵ 假设已经有A与B建立了链接,此时A主动断开连接后,这时候发出的一个ACK,如果没有Time_Wait(2MSL)时间,直接断开连接后立即启用一个新的网络连接,如果有一个来自上个连接的数据包,会直接对当前连接连接造成影响,所以必须进行一个2MSL的等待时间。
4,为什么是2MSL时间:
MSL时间是一个数据包在网络中最大的存活时间。如果超过这个时间,就会在网络传输中消失。一般这个时间在Window环境下就是2分钟,所以2MSL就是4分钟,这个具体的时间根据环境不同有所减少。而之所以是2MSL,主要原因在两个端口之间进行传输,从传输到B端口再从B端口传回来,至少需要2个包,所以规定的时间为2MSL。
5,若是在Time_Wait时间内,还是由于一些原因(路由异常,数据处理延迟,等待超时),造成最后一个ACK没能正常到达,服务器会怎么样?
首先,若服务器多次发Fin得不到回应,根据项目不同,必然是有响应的超时异常处理,但一般情况下不会很少出现这种极端情况,所以哪怕在A端已经关闭,B端发送一个Fin之后,A端也会反馈一个RST分节,这个数据包会在B端被识别成异常错误。
6,如果在Time_Wait状态ACK数据丢失,那A与B如果再次进行数据确认?
TCP协议提供一种超时重传机制,主要根据TCP提供的定时器进行控制,而这种情况下的重传,时间为RRT(数据往返时间),由于路由器和网络流量均会变化,所以RRT时间也是经常变动的。这个时间长短的变动同样是TCP进行监控修改的。具体算法请参考TCP/IP详解:卷一。
7,Time_Wait状态必须等待2MSL时间吗?
当然不是,某些特殊情况A端需要进行大量并且快速的建立连接-断开连接的操作,所以我们有时候不能接受2-4分钟左右的重新等待时间,这时候可以通过设置TCP的配置文件 /etc/sysctl.conf 来改变Time_Wait状态的时间,具体修改内容如下:
编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然后执行/sbin/sysctl -p让参数生效。
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时间
修改之后,再用命令查看TIME_WAIT连接数netstat -ant |grep “TIME_WAIT” |wc –l
在没有nat情况下还需要设置net.ipv4.tcp_timestamps = 1才能生效。
8,若设置了上述时间,我们如何确保Time_Wait的两个作用?
若要设置快速重用的属性,前提也必须设置net.ipv4.tcp_timestamps = 1,TCP就会为数据包添加两个”字节时间字段”,第一个4字节记录发送该数据包的时间,第二个4字节字段用来保存最近一次接受对方发送到数据的时间。有了时间段,我们就可以通过计算时间,来防止延迟的数据到达。但确保双关性可能会出现问题,但就算A段快速关闭,数据丢失下B段重发Fin,会回复一个RST包,表达是异常。
上述大部分都是通过TCP/IP协议与博客了解,部分是通过与朋友讨论总结,若出现错误,请大神们指点