绕不开的TCP之超时重传

前文介绍了TCP建立连接和断开连接的方式。那在连接建立之后,TCP如何保证数据的可靠传输的呢?毕竟现实的网络环境是这样的复杂,出错、超时和丢包的种种问题时有发生,背后的秘密在哪里呢?跟随我们的文章,一起探究一下吧。

TCP重传机制

TCP协议是一种面向连接的可靠的传输层协议,它保证数据可靠传输的基本原理是在发送一个数据之后,就开启一个定时器,若是在这个时间内没有收到刚才发送数据的ACK确认报文(是通过确认序号的方式进行确认,即刚才发送数据的序列号+1),则对该报文进行重传。如果一直失败,满一定次数后就会放弃并发送一个复位信号。

显而易见,这个定时器的时间(RTO)相当关键,关系着网络资源是否被有效利用。

如果RTO设置过小,部分报文可能遇到网络拥堵或者延迟比较大的情形,这样就会频繁重传,浪费带宽。如果RTO设置过大的话,发送端需要等待过长时间才能发现数据丢失,影响网络的传输效率,造成的表象就是后端系统响应时间过长甚至超时,显然会给用户造成恶劣的影响,这是我们需要坚决规避的。

那设置RTO是否有依据呢?

一般RTO是根据网络中的RTT(传输往返时间)来自适应调整的。具体算法这边就不赘叙了。

接下来让我们通过两幅图来了解一下重传机制吧。
在这里插入图片描述
主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B。
如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发。

但是主机A没收到确认应答也可能是ACK丢失了,如下图所示。

在这里插入图片描述
这种情况下, 主机B会收到很多重复数据。

那么TCP协议需要识别出哪些包是重复的, 并且把重复的丢弃。那TCP是如何去重的呢?

答案就是序列号(TCP将每个字节的数据都进行的编号),如下图所示:

在这里插入图片描述
每次主机B的确认应答都带有对应的确认序列号, 用来告知主机A, 我已经收到了哪些数据(收到的数据为确认序列号-1以下的字节数据),下一次你要从哪里开始发送,而已经接收的数据序列号会缓存在本地等待上层应用程序消费,如果已经重复了,则会丢弃。

比如, 主机A向主机B发送了1005字节的数据, 服务器返回给客户端的确认序号是1003, 那么说明服务器只收到了1-1002的数据. 1003的数据肯定没有收到,至于1004, 1005则不确定,即使收到了,也会暂时缓存, 等主机A重发1003收到后,直接向主机A确认应答,此时确认序列号应该为1006。

重传定时器

上面的定时器被称作重传定时器(Retransmission Timer),其在TCP发送报文段时,就会被创建(与该特定报文相关)。可能发生以下两种情况:
1.若在计时器截止时间到之前收到了对此特定报文段的确认,则撤销此计时器。

2.若在收到了对此特定报文段的确认之前计时器截止时间到,则重传此报文段,并将计时器复位。

是否还有其他定时器呢?如果有,它们又分别应用在什么场景呢?

(1)坚持计时器

先来考虑以下情景:发送端向接收端发送数据包直到接收窗口填满了,然后接收窗口告诉发送方接收窗口填满了,请停止发送数据。此时的状态称为“零窗口”状态,发送端和接收端窗口大小均为0。直到接收TCP发送确认并宣布一个非零的窗口大小,但这个确认会丢失。

众所周知,TCP对确认是不需要发送确认的。若确认丢失了,接收TCP并不知道,而是会认为它已经完成了任务,并等待着发送TCP接着会发送更多的报文段。但发送TCP由于没有收到确认,就一直等待对方发送确认来通知窗口大小,由此导致双方的TCP都在永远的等待着对方。要打开这种死锁,TCP需要为每一个链接使用一个坚持计时器。

当发送TCP收到窗口大小为0的确认时,就启动坚持计时器。当坚持计时器期限到时,发送TCP就发送一个特殊的报文段,叫做探测报文。这个报文段只有一个字节的数据。它有一个序号,但它的序号永远不需要确认;甚至在计算机对其他部分的数据的确认时该序号也被忽略。探测报文段提醒接收TCP:确认已丢失,必须重传。坚持计时器的值设置为重传时间的数值。但是,若没有收到从接收端来的响应,则需发送另一个探测报文段,并将坚持计时器的值加倍和复位。发送端继续发送探测报文段,将坚持计时器设定的值加倍和复位,直到这个值增大到门限值(通常是60秒)为止。在这以后,发送端每隔60秒就发送一个探测报文,直到窗口重新打开。

(2)保活计时器

保活计时器使用在某些实现中,用来防止在两个TCP之间的连接出现长时间的空闲。假定客户端建立了到服务器的连接,并传送了一些数据,然后就保持静默了。也许是这个客户出故障了。在这种情况下,这个连接将永远的处理打开状态。
要解决这种问题,在大多数的实现中都是使服务器设置保活计时器。每当服务器收到客户的信息,就将计时器复位。通常设置为两小时。若服务器过了两小时还没有收到客户的信息,他就发送探测报文段。若发送了10个探测报文段(每一个75秒)还没有响应,就假定客户除了故障,因而就终止了该连接。这种连接的断开当然不会使用四次握手,而是直接硬性的中断和客户端的TCP连接。

(3)时间等待计时器

时间等待计时器是在四次握手的时候使用的,上文已经提到过,这边就不重复了。

以上是关于TCP超时重传的探索,希望可以给大家带来收获。

其他文章可以关注微信公众号测试架构师养成记,还有价值999的资料可以领哦~
在这里插入图片描述

发布了49 篇原创文章 · 获赞 15 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_43164644/article/details/102490819