【计算机网络】TCP面试知识(2)TCP重传机制有哪些?

TCP 实现可靠传输的⽅式之⼀,是通过序列号与确认应答。

在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回⼀个确认应答消息,表示已收到消息。

在这里插入图片描述

但在错综复杂的⽹络,并不⼀定能如上图那么顺利能正常的数据传输,万⼀数据在传输过程中丢失了呢?所以 TCP 针对数据包丢失的情况,会⽤重传机制解决。

常⻅的重传机制:

  • 超时重传
  • 快速重传
  • SACK
  • D-SACK

1、超时重传

重传机制的其中⼀个⽅式,就是在发送数据时,设定⼀个定时器,当超过指定的时间后,没有收到对⽅的 ACK确认应答报⽂,就会重传该数据,也就是我们常说的超时重传。

TCP 会在以下两种情况发⽣超时重传:

  • 数据包丢失
  • 确认应答丢失

在这里插入图片描述

(1)超时时间应该设置为多少呢?

首先了解一下RTT(Round-Trip Time 往返时延)的定义:

在这里插入图片描述

RTT 就是数据从⽹络⼀端传送到另⼀端所需的时间,也就是包的往返时间。

超时重传时间是以 RTO (Retransmission Timeout 超时重传时间)表示。

假设在重传的情况下,超时时间 RTO 「较⻓或较短」时,会发⽣什么事情呢?

在这里插入图片描述

上图中有两种超时时间不同的情况:

  • 当超时时间 RTO 较⼤时,重发就慢,丢了⽼半天才重传,没有效率,性能差;
  • 当超时时间 RTO 较⼩时,会导致可能并没有丢就重发,于是重传的就快,会增加⽹络拥塞,导致更多的超时,更多的超时导致更多的重传。

【结论】

根据上述的两种情况,我们可以得知,超时重传时间 RTO 的值应该略⼤于报⽂往返 RTT 的值。

在这里插入图片描述

实际上「报⽂往返 RTT 的值」是经常变化的,因为我们的⽹络也是时常变化的。也就因为「报⽂往返 RTT 的值」是经常波动变化的,所以 「超时重传时间 RTO 的值」应该是⼀个动态变化的值。

Linux 是如何计算 RTO 的呢?

估计往返时间,通常需要采样以下两个:

  • 需要 TCP 通过采样 RTT 的时间,然后进⾏加权平均,算出⼀个平滑 RTT 的值,⽽且这个值还是要不断变化的,因为⽹络状况不断地变化。
  • 除了采样 RTT,还要采样 RTT 的波动范围,这样就避免如果 RTT 有⼀个⼤的波动的话,很难被发现的情况。

如果超时重发的数据,再次超时的时候,⼜需要重传的时候,TCP 的策略是超时间隔加倍。

也就是每当遇到⼀次超时重传的时候,都会将下⼀次超时时间间隔设为先前值的两倍。两次超时,就说明⽹络环境差,不宜频繁反复发送。

2、快速重传

快速重传(Fast Retransmit)机制,它不以时间为驱动,⽽是以数据驱动重传。

在这里插入图片描述

在上图,发送⽅发出了 1,2,3,4,5 份数据:

  • 第⼀份 Seq1 先送到了,于是就 Ack 回 2;
  • 结果 Seq2 因为某些原因没收到,Seq3 到达了,于是还是 Ack 回 2;
  • 后⾯的 Seq4 和 Seq5 都到了,但还是 Ack 回 2,因为 Seq2 还是没有收到;
  • 发送端收到了三个 Ack = 2 的确认,知道了 Seq2 还没有收到,就会在定时器过期之前,重传丢失的 Seq2。
  • 最后,收到了 Seq2,此时因为 Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。

所以,快速重传的⼯作⽅式是当收到三个相同的 ACK 报⽂时,会在定时器过期之前,重传丢失的报⽂段。

快速重传机制只解决了⼀个问题,就是超时时间的问题,但是它依然⾯临着另外⼀个问题。就是重传的时候,是重传之前的⼀个,还是重传所有的问题。

⽐如对于上⾯的例⼦,是重传 Seq2 呢?还是重传 Seq2、Seq3、Seq4、Seq5 呢?因为发送端并不清楚这连续的三个 Ack 2 是谁传回来的。

根据 TCP 不同的实现,以上两种情况都是有可能的。可⻅,这是⼀把双刃剑。

为了解决不知道该重传哪些 TCP 报⽂,于是就有 SACK ⽅法。

3、SACK 方法

SACK ( Selective Acknowledgment 选择性确认):这种⽅式需要在 TCP 头部「选项」字段⾥加⼀个 SACK 的东⻄,它可以将缓存的地图发送给发送⽅,这样发送⽅就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。

如下图,发送⽅收到了三次同样的 ACK 确认报⽂,于是就会触发快速重传机制,通过 SACK 信息发现只有200~299 这段数据丢失,则重发时,就只选择了这个 TCP 段进⾏重复。

在这里插入图片描述

如果要⽀持 SACK ,必须双⽅都要⽀持。在 Linux 下,可以通过 net.ipv4.tcp_sack 参数打开这个功能(Linux2.4 后默认打开)。

4、Duplicate SACK

Duplicate SACK ⼜称 D-SACK ,其主要使⽤了 SACK 来告诉「发送方」有哪些数据被重复接收了。

(1)情形1:ACK 丢包

在这里插入图片描述

  • 「接收⽅」发给「发送⽅」的两个 ACK 确认应答都丢失了,所以发送⽅超时后,重传第⼀个数据包(3000 ~3499)
  • 于是「接收⽅」发现数据是重复收到的,于是回了⼀个 SACK = 3000~3500,告诉「发送⽅」 3000~3500的数据早已被接收了,因为 ACK 都到了 4000 了,已经意味着 4000 之前的所有数据都已收到,所以这个SACK 就代表着 D-SACK 。
  • 这样「发送⽅」就知道了,数据没有丢,是「接收⽅」的 ACK 确认报⽂丢了。

(2)情形2:网络延时

在这里插入图片描述

  • 数据包(1000~1499) 被⽹络延迟了,导致「发送⽅」没有收到 Ack 1500 的确认报⽂。
    ⽽后⾯报⽂到达的三个相同的 ACK 确认报⽂,就触发了快速重传机制,但是在重传后,被延迟的数据包(1000~1499)⼜到了「接收⽅」;
  • 所以「接收⽅」回了⼀个 SACK=1000~1500,因为 ACK 已经到了 3000,所以这个 SACK 是 D-SACK,表示收到了重复的包。
  • 这样发送⽅就知道快速重传触发的原因不是发出去的包丢了,也不是因为回应的 ACK 包丢了,⽽是因为⽹络延迟了。

【 D-SACK 优点】

  • 可以让「发送⽅」知道,是发出去的包丢了,还是接收⽅回应的 ACK 包丢了;
  • 可以知道是不是「发送⽅」的数据包被⽹络延迟了;
  • 可以知道⽹络中是不是把「发送⽅」的数据包给复制了;

【打开方式】

在 Linux 下可以通过 net.ipv4.tcp_dsack 参数开启/关闭这个功能(Linux 2.4 后默认打开)。

整理自小林coding所著的《图解网络》,仅做学习用,侵删

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值