【网络编程】TCP维护的七个定时器


TCP 是面向连接的,可靠的流式传输的传输层协议,它使用的方法之一就是·确认从另一端收到的数据【确认应答机制】。但是数据发送和确认都可能会丢失。TCP 通过在·发送时设置一个定时器·来解决这个问题。如果当定时器溢出时还没收到确认,它就会重传该数据。关键在于超时和重传策略,即怎样决定超时的时间间隔如何确定重传的频率。

1.建立连接定时器(connection-establishment timer)

顾名思义,这个定时器是在建立连接的时候使用的, 我们知道, TCP建立连接需要3次握手, 如下图所示:
TCP三次握手
如果client在连接server的时候,在发送SYN的时候,会启动一个定时器(默认应该是3秒),如果SYN包丢失(3秒收不到回复)了,那么3秒以后会重新发送SYN包的(当然还会启动一个新的定时器,设置成6秒超时),当然也不会一直没完没了的发SYN包。在/proc/sys/net/ipv4/tcp_syn_retries 可以设置到底要重新发送几次SYN包。(默认6次)
在这里插入图片描述
参考博客:关于TCP的syn丢失的事情

2.重传定时器(retransmission timer)

对于TCP发送出去的数据包是先加载到内存,在发送出去, 需要等待对端发来ACK才能从内存里面删除, 那么如果对端没有发送ACK怎么办? 重传呗, 在发送数据的同时,在设置一个超时时间(RTO),如果在这个超时时间内, 没有收到ACK,那么就重传刚才发送的数据。
·RTT(Round Trip Time):一个连接的往返时间,即数据发送时刻到接收到确认的时刻的差值;
RTO(Retransmission Time Out):重传超时时间,即从数据发送时刻算起,超过这个时间便执行重传。
RTT和RTO 的关系是:由于网络波动的不确定性,每个RTT都是动态变化的,所以RTO也应随着RTT动态变化。
重传定时器在TCP发送数据时设定,在计时器超时后没有收到返回的确认ACK,发送端就会重新发送队列中需要重传的报文段。使用RTO重传计时器一般有如下规则:

当TCP发送了位于发送队列最前端的报文段后就启动这个RTO计时器;
如果队列为空则停止计时器,否则重启计时器;
当计时器超时后,TCP会重传发送队列最前端的报文段;
当一个或者多个报文段被累计确认后,这个或者这些报文段会被清除出队列

重传计时器保证了接收端能够接收到丢失的报文段,继而保证了接收端交付给接收进程的数据始终的有序完整的。因为接收端永远不会把一个失序不完整的报文段交付给接收进程。
参考博客:关于TCP的syn丢失的事情

3.延迟应答定时器(delayed ACK timer)

顾名思义,这个定时器是在延迟应答的时候使用的。
为什么要延迟应答呢? 比如客户端发一段数据给服务端,服务端本应该立刻回ACK给客户端的,延迟应答是为了提高网络传输的效率,比如服务端收到客户端的数据后,不是立刻回ACK给客户端,而是等一段时间(一般最大200ms),这样如果服务端要是有数据需要发给客户端,那么这个ACK就和服务端的数据一起发给客户端了,这样比立即回给客户端一个ACK节省了一个数据包。

4.坚持定时器(persist timer)

坚持定时器是在收到receive window为0的时候开始启动的.
这里写图片描述

假设一个场景:如果一个确认丢失了,则双方就有可能因为等待对方而使连接终止,接收方等待接收数据(因为它已经向发送方通告了一个非0的窗口), 而发送方在等待允许它继续发送数据的窗口更新。为防止这种死锁情况的发生,发送方使用一个坚持定时器(persist timer)来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送方发出的报文段称为窗口探查(window probe)。

计算坚持定时器时使用了普通的TCP指针退避窗口探查报文包含一个字节的数据。首次超时时间是1.5秒,之后的超时时间增加一倍,但总在5~60秒之间。
坚持状态与重传超时之间一个不同的特点就是TCP从不放弃发送窗口探查。这些探查每隔60秒发送一次,这个过程将持续到窗口打开或者应用进程使用的连接被终止。

附:糊涂窗口综合症

糊涂窗口综合症:接收方可以通告一个小的窗口(而不是一直等到有大的窗口时才通告),而发送方可以通过这个小窗口发送少量的数据(而不是等待其它的数据以便发送一个大的报文段),即,少量的数据通过连接交换,而不是满长度的报文段,TCP的传输效率可想而知。

如何避免“糊涂窗口综合症”:
接收方:接收方不通告小窗口,除非增加一个报文段(MMS)或者接收方缓存空间的一半,否则通告为0。
发送方
(1)可以发送一个满长度的报文段(MMS)
(2)可以发送至少接收方通告窗口一半的报文段
(3)能够发送手头的所有数据并且不希望接收ACK,或者该连接禁止了Nagle算法时,可以发送任意数据。
坚持定时器工作流程:

(1)发送端收到0窗口通告后,就启动坚持定时器,并在定时器溢出的时候向客户端查询窗口是否已经增大。
(2)在定时器未到,就收到非零通告,则关闭该定时器,并发送数据。
(3)若定时器已到,还没有收到非零通告,就发探查报文。
(4)如果探查报文ACK的通告窗口为0,就将坚持定时器的值加倍,TCP的坚持定时器使用1,2,4,8,16……64秒这样的普通指数退避序列来作为每一次的溢出时间,重复1、2、3步,如果通告窗口非零,发送数据,关闭定时器。

5.保活定时器(keepalive timer)

现实中可能存在这么一种空闲TCP连接:没有任何数据流通过。也就是说,如果TCP连接的双方都没有向对方发送数据,则在两个TCP模块之间不交换任何信息,这意味着我们可以启动一个客户与服务器建立连接,然后长时间不使用,而连接依然保持中间的路由器可以崩溃和重启,电话线可以被挂断再连接,但只要两端的主机没有被重启,则连接依然保持建立。
然而,许多时候一个服务器希望知道客户主机是否崩溃并关机或者崩溃又重新启动,许多实现提供的保活定时器可以提供这种能力。保活并不是TCP规范中的一部分。

保活就是:防止两端的TCP在连接期间长时间处于空暇状态。一般是server设置的计时器,超时通常设置为2h,当server超过了2h还没有收到客户的任何信息,server就向客户发送过一个探測报文段,若连续发送了10个探測报文段(每个75s一个)还没有响应,就觉得客户出了故障,直接终止这个连接。

  • 保活定时器工作原理:

如果一个 给定的连接在2小时内没有任何动作,那么服务器就向客户发送一个探查报文段。客户主机必须处于以下4个状态之一:
(1)客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方的正常工作的,服务器在2小时内将保活定时器复位。
(2)客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应,服务器将不能收到对探查的响应,并在75秒后超时,总共发送10个探查,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。
(3)客户主机崩溃并已经重新启动。这是服务器将收到一个对其保活探查的响应,但这个响应是一个RST复位,使得服务器终止这个连接。
(4)客户主机正常运行,但是从服务器不可达。这与状态2相同,因为TCP不能够区分状态4与2之间的区别,它所能发现的就是没有收到探查的响应。

服务器不用关注客户主机被关闭和重新启动的情况,当系统被操作员关闭时,所有的应用进程也被终止,这会使客户的TCP在连接上发出一个FIN。接收到FIN将使服务器的TCP向服务器进程报告文件结束,使服务器可以检测到这个情况。

6.FIN_WAIT_2定时器(FIN_WAIT_2 timer)

在主动关闭的一端调用完close以后(发FIN包给对端, 并且收到对端对FIN的ACK)则进入到FIN_WAIT_2状态,那么这个时候如果和对端之间的网络坏了或者对端程序有问题了一直不close,或者对端机器直接断电了,本端不能一直傻等吧,所以就需要这个定时器,如果在这个定时器超时的时候,还是没收到对端的FIN包,那么不好意思不等了,直接释放这个链接。

7.TIME_WAIT定时器 (TIME_WAIT timer, 也叫 2MSL timer)

在连接终止期使用,当TCP关闭连接时,并不认为这个连接就真正关闭了,在时间等待期间,连接还处于一种中间过度状态。这样就可以使重复的FIN报文段在到达终点后被丢弃,这个计时器的值通常设置为一格报文段寿命期望值的两倍。

·TIME_WAIT是主动关闭连接的一端最后进入的状态,而不是直接变成CLOSED的状态,为什么呢?

  • 第一个原因是万一最后一个ACK丢失了,对端会重传的,这个在超时之前的重新收到对端的FIN也可以回ACK,而不是RST。
  • 另外一个原因是防止老连接的包在新连接里面出现,影响了新连接。有这个2MSL的时间,可以在2个MSL时间之内不会建立同样四元组(源IP, 源端口,目的IP,目的端口)的连接,也就不会出现老的包影响新连接的事情。

·为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

MSL(Maximum Segment Lifetime)表示报文段最大生存时间,它表示任何报文段被丢弃前在网络内的最长时间,实际上这个时间和 TTL 有关(TTL 是 IP 协议中的一个概念,表示能够经历的路由器的跳数,这个跳数是有限制的,最大值为 255)。但是MSL并不用跳数,而是用时间来计算。不同系统中,MSL 定义的大小不一样RFC 规定,MSL = 2 分钟,而实际实现中,通常是 30 秒、1 分钟。也就是说报文在网络中存在的时间不能超过MSL规定的时间,同时也间接的说明了tcp连接在TIME_WAIT状态必须存在2MSL才能进入CLOSE状态。

参考链接:TIME_WAIT详解

©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值