TCP详解之重传机制

2023-09-17 21:48:43

TCP详解之重传机制

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

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

正常的数据传输

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

1. 超时重传

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

TCP会在一下两种情况发生超时重传:

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

超时重传的两种情况

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

我们先来了解一下什么是RTT(Round-Trip Time往返时延),从下图我们可以知道:

RTT

RTT指的是数据发送时刻到接收到确认应答的时刻的差值,也就是包的往返时间。超时重传时间是以RTO(Retransmission Timeout超时重传时间)表示。假设在重传的情况下,超时时间RTO「较长或较短」时,会发生什么事情呢?

超时时间较长与较短

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

  • 当超时时间RTO较大时,重发就慢,丢了老半天才重发,就没有效率,性能差;
  • 当超时时间RTO较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥堵,导致更多的超时,更多的超时导致更多的重发。

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

RTO 应略大于 RTT

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

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

超时触发重传存在的问题是,超时周期可能相对较长。那是不是可以有更快的方式呢?

于是就可以用「快速重传」机制来解决超时重传的时间等待。

2. 快速重传

TCP还有另外一种快速重传(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 报文时,会在定时器过期之前,重传丢失的报文段。

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

举个例子,假设发送方发了 6 个数据,编号的顺序是 Seq1 ~ Seq6 ,但是 Seq2、Seq3 都丢失了,那么接收方在收到 Seq4、Seq5、Seq6 时,都是回复 ACK2 给发送方,但是发送方并不清楚这连续的 ACK2 是接收方收到哪个报文而回复的, 那是选择重传 Seq2 一个报文,还是重传 Seq2 之后已发送的所有报文呢(Seq2、Seq3、 Seq4、Seq5、 Seq6) 呢?

  • 如果只选择重传 Seq2 一个报文,那么重传的效率很低。因为对于丢失的 Seq3 报文,还得在后续收到三个重复的 ACK3 才能触发重传。
  • 如果选择重传 Seq2 之后已发送的所有报文,虽然能同时重传已丢失的 Seq2 和 Seq3 报文,但是 Seq4、Seq5、Seq6 的报文是已经被接收过了,对于重传 Seq4 ~Seq6 折部分数据相当于做了一次无用功,浪费资源。

可以看到,不管是重传一个报文,还是重传已发送的报文,都存在问题。

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

3. SACK

还有一种实现重传机制的方式叫:SACK( Selective Acknowledgment), 选择性确认

这种方式需要在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将已收到的数据的信息发送给「发送方」,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据

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

选择性确认

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

4. Duplicate SACK

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

下面举例两个栗子,来说明 D-SACK 的作用。

栗子一号:ACK 丢包

ACK 丢包

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

栗子二号:网络延时

网络延时

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

可见,D-SACK 有这么几个好处:

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

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

更多推荐

Ubuntu 安装 CUDA 与 CUDNN GPU加速引擎

一、NVIDIA(英伟达)显卡驱动安装NVIDIA显卡驱动可以通过指令sudoaptpurgenvidia*删除以前安装的NVIDIA驱动版本,重新安装。1.1.关闭系统自带驱动nouveau注意!在安装NVIDIA驱动以前需要禁止系统自带显卡驱动nouveau:可以先通过指令lsmod|grepnouveau查看no

嵌入式笔试面试刷题(day11)

文章目录前言一、字节流,数据报,报文二、makefile怎么引入库和模块三、多次free一块内存空间会怎么样四、字符操作函数越界会发生什么五、QT中一个信号可以连接多个槽函数吗六、QT中一个槽函数可以对应多个信号吗总结前言本篇文章继续刷题。一、字节流,数据报,报文1.数据报(Datagram):数据报是一种独立的、特定

Linux:基础开发工具之Makefile和缓冲区的基本概念

文章目录动静态库自动化构建代码缓冲区原理实现具体实现动静态库首先要知道什么是链接:C程序中,并没有定义printf的函数实现,且在预编译中包含的stdio.h中也只有该函数的声明,而没有定义函数的实现系统把这些函数实现都被做到名为libc.so.6的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径“/usr

JAVA面经整理(2)

一)解决哈希冲突的方法有哪些?哈希冲突指的是在哈希表中,不同的键值映射到了相同的哈希桶,也就是数组索引,导致键值对的冲突1)设立合适的哈希函数:通过哈希函数计算出来的地址要均匀的分布在整个空间中2)负载因子调节:2.1)开放地址法:1)当发生哈希冲突时,如果哈希表中没有装满,说明哈希表中一定还有空余位置,那么可以把ke

基于Python Django的公务员考试信息管理系统

文章目录1简介2.技术栈3功能分析4功能具体设计4.1软件功能模块设计4.2数据库设计与实现4.2.1概念模型设计4.2.2数据库逻辑结构设计5系统详细设计5.1系统功能模块5.2管理员功能模块六源码咨询1简介公务员考试信息管理系统的开发运用Python技术,MIS的总体思想,以及MYSQL等技术的支持下共同完成了该系

Linux系统编程(信号处理 sigacation函数和sigqueue函数 )

文章目录前言一、sigaction二、sigqueue函数三、代码示例总结前言本篇文章我们来介绍一下sigacation函数和sigqueue函数。一、sigactionsigaction是一个用于设置和检查信号处理程序的函数。它允许我们指定信号的处理方式,包括指定一个函数作为信号处理程序、设置标志位以及指定信号处理程

Linux系统编程(信号处理机制)

文章目录前言一、中断,异常,信号的区别二、信号在Linux中的标识三、信号处理相关函数四、代码实验总结前言本篇文章我们来讲解信号的处理机制,信号处理在Linux操作系统中必不可少,这一点值得大家注意,信号又会与中断,异常一起讨论,那么下面我们就来看看到底什么是信号吧。一、中断,异常,信号的区别中断、异常和信号是计算机系

MAC MINI 2012安装Montery折腾笔记

MACMINI2012安装Montery折腾笔记(作为电视盒子/远程开发机)起因:手头有个macmini,2018年买的2手。一直都是10.12系统,处理python和苹果开发都受制于旧系统,很多软件也装不上,于是有了升级的需求,打算折腾下再战3年直接升级使用因特网恢复系统模式,恢复到最新适配的版本开机时,按Win+A

一些docker笔记

一些docker笔记docker是一个跨平台,可迁移的应用虚拟化,容器化服务平台Docker口号1:Build,ShipandRun(构建,发送和运行)Docker口号2:Buildonce,Runanywhere(构建一次,到处能用)docker一些概念docker仓库官方有dockeHub仓库,也可以使用阿里、网易

Spring Authorization Server入门 (十八) Vue项目使用PKCE模式对接认证服务

Vue单页面项目使用授权码模式对接流程说明以下流程摘抄自官网在本例中为授权代码流程。授权码流程的步骤如下:客户端通过重定向到授权端点来发起OAuth2请求。对于公共客户端,此步骤包括生成code_verifier并计算code_challenge,然后将其作为查询参数发送。如果用户未通过身份验证,授权服务器将重定向到登

PostgreSQL16源码包编译安装

一、安装环境操作系统:CentOSLinuxrelease7.8.2003(Core)PostgreSQL版本:16服务器IP地址:192.168.0.244Firewalld关闭、selinux关闭笔者本次选用最新v16版本进行部署二、pg数据库安装包下载下载地址:https://www.postgresql.org

热文推荐