TCP是面向连接的,可靠 的,流式 传输的协议。
在TCP的里面有7种定时器分别是
1. 建立连接定时器 (connection-establishment timer)
2. 重传定时器 (retransmission timer)
3. 延迟应答定时器 (delayed ACK timer)
4. 坚持定时器 (persist timer)
5. 保活定时器 (keepalive timer)
6 FIN_WAIT_2定时器 (FIN_WAIT_2 timer)
7. TIME_WAIT定时器 (TIME_WAIT timer, 也叫 2MSL timer)
1. 建立连接定时器(connection-establishment timer)
顾名思义,这个定时器是在建立连接的时候使用的, 我们知道, TCP建立连接需要3次握手:
image.png如果client在连接server的时候, 在发送SYN的时候, 会启动一个定时器(在 3.10 版本中首次超时时间是 1 s,一些老版本中是 3 s。),如果SYN包丢失了, 那么1秒以后会重新发送SYN包的(当然还会启动一个新的定时器, 设置成2秒超时),当然也不会一直没完没了的发SYN包, 在/proc/sys/net/ipv4/tcp_syn_retries 可以设置到底要重新发送几次SYN包。
2. 重传定时器(retransmission timer)
对于TCP发送出去的数据包, 需要等待对端发来ACK才能从内存里面删除, 那么如果对端没有发送ACK怎么办? 重传。
在发送数据的同时,再设置一个超时时间(一般设置成2个RTT的时间),如果在这个超时时间内, 没有收到ACK,那么就重传刚才发送的数据。
3. 延迟应答定时器(delayed ACK timer)
顾名思义, 这个定时器是在延迟应答的时候使用的。
为什么要延迟应答呢?
比如客户端发一段数据给服务端, 服务端本应该立刻回ACK给客户端的, 延迟应答是为了提高网络传输的效率, 比如服务端收到客户端的数据后, 不是立刻回ACK给客户端, 而是等一段时间(一般最大200ms),这样如果服务端要是有数据需要发给客户端,那么这个ACK就和服务端的数据一起发给客户端了, 这样比立即回给客户端一个ACK节省了一个数据包。
4. 坚持定时器(persist timer)
坚持定时器是在收到receive window为0的时候开始启动的, 为什么需要这个呢?
比如最后一个ACK丢了, 那么发送端就永远认为接收端的窗口是0, 那么就发不了数据了。
这个时候就需要坚持定时器,每隔一段时间(第一个探测包是在收到窗口为0的消息后的5秒)发送一个字节的探测包给服务端, 如果服务端窗口不是0了, 会在ack里面更新窗口大小的。
5. 保活定时器(keepalive timer)
如果客户端和服务端长时间没有数据交互,那么需要保活定时器来判断是否对端还活着,但是这个其实很不实用,因为默认是2小时没有数据交互才探测,时间实在是太长了。
如果你真的要确认对端是否活着, 那么应该在应用层自己实现心跳包,而不是依赖于这个保活定时器。
# TCP KeepAlive 机制,保活时间、保活时间间隔和保活探测次数
net.ipv4.tcp_keepalive_time
net.ipv4.tcp_keepalive_intvl
net.ipv4.tcp_keepalve_probes
默认设置是 7200 秒(2 小时)、75 秒和 9 次探测。
如果使用 TCP 自身的 keep-Alive 机制,在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个“死亡”连接。
这个时间是怎么计算出来的呢?
其实是通过 2 小时,加上 75 秒乘以 9 的总和。
实际上,对很多对时延要求敏感的系统中,这个时间间隔是不可接受的。
6. FIN_WAIT_2定时器 (FIN_WAIT_2 timer)
image.png在主动关闭的一端调用完close以后(发FIN包给对端, 并且收到对端对FIN的ACK)则进入到FIN_WAIT_2状态, 那么这个时候如果和对端之间的网络坏了或者对端程序有问题了一直不close, 或者对端机器直接掉电了, 本端不能一直傻等, 所以就需要这个定时器.
如果在这个定时器超时的时候,还是没收到对端的FIN包, 那么不好意思, 不等了, 直接释放这个链接。
这个定时器的时间是多少呢?可以从/proc/sys/net/ipv4/tcp_fin_timeout里面看到。
7. TIME_WAIT定时器 (TIME_WAIT timer, 也叫 2MSL timer)
image.pngTIME_WAIT是主动关闭连接的一端最后进入的状态, 而不是直接变成CLOSED的状态, 为什么呢?
第一个原因是万一最后一个ACK丢失了, 对端会重传的, 这个在超时之前的重新收到对端的FIN也可以回ACK, 而不是RST。
另外一个原因是防止老的连接的包在新的连接里面出现, 影响了新的连接。
有这个2MSL的时间,可以在2个MSL时间之内不会建立同样四元组(源IP, 源端口,目的IP,目的端口)的连接,也就不会出现老的包影响新连接的事情。
TCP包括两个定时器函数:一个函数为200ms调用一次(快速定时器);另一个函数每500ms调用一次(慢速定时器)。
延迟ACK定时器与其它6个定时器有所不同,如果摸个连接上设定了延迟ACK定时器,那么下一个200ms定时器超时后,延迟的ACK必须被发送(ACK的延时时间必须在0-200ms之间)。
其它的定时器每500ms递减一次,计时器减为0时,就触发相应的动作。
参考
TCP协议中的七个定时器
https://www.dandelioncloud.cn/article/details/1456673177345781762
TCP中的7种定时器
http://orcl.net.cn/show.php?id=426
网友评论