TCP详解之重传机制

2023-11-11

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 后默认打开)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP详解之重传机制 的相关文章

  • Unix 命令列出包含字符串但*不*包含另一个字符串的文件

    如何递归查看包含一个字符串且不包含另一个字符串的文件列表 另外 我的意思是评估文件的文本 而不是文件名 结论 根据评论 我最终使用了 find name html exec grep lR base maps xargs grep L ba
  • 从 PL/SQL 调用 shell 脚本,但 shell 以 grid 用户而非 oracle 身份执行

    我正在尝试使用 Runtime getRuntime exec 从 Oracle 数据库内部执行 shell 脚本 在 Red Hat 5 5 上运行的 Oracle 11 2 0 4 EE CREATE OR REPLACE proced
  • 创建 jar 文件 - 保留文件权限

    我想知道如何创建一个保留其内容的文件权限的 jar 文件 我将源代码和可执行文件打包在一个 jar 文件中 该文件将在使用前提取 人们应该能够通过运行批处理 shell 脚本文件立即运行示例和演示 然后他们应该能够修改源代码并重新编译所有内
  • Android:ANT 构建失败,并显示 google-play-services-lib:“解析为没有项目的 project.properties 文件的路径”

    我正在尝试使用 ANT 构建我的应用程序 但在包含 google play services lib 库项目后 我惨遭失败 Step 1 我在 project properties 文件中设置了对库项目的引用 android library
  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 如何检测并找出程序是否陷入死锁?

    这是一道面试题 如何检测并确定程序是否陷入死锁 是否有一些工具可用于在 Linux Unix 系统上执行此操作 我的想法 如果程序没有任何进展并且其状态为运行 则为死锁 但是 其他原因也可能导致此问题 开源工具有valgrind halgr
  • 从 csv 文件中删除特定列,保持输出上的相同结构[重复]

    这个问题在这里已经有答案了 我想删除第 3 列并在输出文件中保留相同的结构 输入文件 12 10 10 10 10 1 12 23 1 45 6 7 11 2 33 45 1 2 1 2 34 5 6 I tried awk F 3 fil
  • 如何在bash中使用jq从变量中包含的json中提取值

    我正在编写一个 bash 脚本 其中存储了一个 json 值 现在我想使用 Jq 提取该 json 中的值 使用的代码是 json val code lyz1To6ZTWClDHSiaeXyxg redirect to http examp
  • 为什么 Linux perf 使用事件 l1d.replacement 来处理 x86 上的“L1 dcache misses”?

    在英特尔 x86 上 Linux用途 https stackoverflow com a 52172985 149138事件l1d replacements来实施其L1 dcache load misses event 该事件定义如下 计数
  • 为什么内核需要虚拟寻址?

    在Linux中 每个进程都有其虚拟地址空间 例如 32位系统为4GB 其中3GB为进程保留 1GB为内核保留 这种虚拟寻址机制有助于隔离每个进程的地址空间 对于流程来说这是可以理解的 因为有很多流程 但既然我们只有 1 个内核 那么为什么我
  • 从 Python 调用 PARI/GP

    我想打电话PARI GP http pari math u bordeaux fr dochtml gpman html仅从Python计算函数nextprime n 对于不同的n是我定义的 不幸的是我无法得到帕里蟒蛇 http code
  • chown:不允许操作

    我有问题 我需要通过 php 脚本为系统中的不同用户设置文件所有者权限 所以我通过以下命令执行此操作 其中 1002 是系统的用户 ID file put contents filename content system chown 100
  • Linux 中的动态环境变量?

    Linux 中是否可以通过某种方式拥有动态环境变量 我有一个网络服务器 网站遵循以下布局 site qa production 我想要一个环境变量 例如 APPLICATION ENV 当我在 qa 目录中时设置为 qa 当我在生产目录中时
  • 如何有效截断文件头?

    大家都知道truncate file size 函数 通过截断文件尾部将文件大小更改为给定大小 但是如何做同样的事情 只截断文件的尾部和头部呢 通常 您必须重写整个文件 最简单的方法是跳过前几个字节 将其他所有内容复制到临时文件中 并在完成
  • NPTL 和 POSIX 线程有什么区别?

    NPTL 和 POSIX 线程之间的基本区别是什么 这两者是如何演变的 POSIX 线程 pthread 不是一个实现 它是几个函数的 API 规范 纸上的标准 英文 其名称以pthread 以及定义在
  • os.Mkdir 和 os.MkdirAll 权限

    我正在尝试在程序开始时创建一个日志文件 我需要检查是否 log如果不创建目录 则目录存在 然后继续创建日志文件 好吧 我尝试使用os Mkdir 也os MkdirAll 但无论我在第二个参数中输入什么值 我都会得到一个没有权限的锁定文件夹
  • Linux:在文件保存时触发 Shell 命令

    我想在修改文件时自动触发 shell 命令 我认为这可以通过注册 inotify 挂钩并调用来在代码中完成system 但是是否有更高级别的 bash 命令可以完成此任务 尝试 inotify 工具 我在复制链接时遇到问题 抱歉 但 Git
  • 如何在apache 2.4.6上安装apxs模块

    我刚刚用过apt get update我的 apache 已更新为2 4 6 我想安装 apxs 来编译模块 但收到此错误 The following packages have unmet dependencies apache2 pre
  • 如何在shell中输出返回码?

    我正在尝试通过调用自定义 shell 脚本sh bin sh c myscript sh gt log txt 2 gt 1 echo 该命令的输出是创建的后台进程的 PID 我想指导 bin sh保存返回码myscript sh到某个文件
  • iptables通过注释删除特定规则

    我需要删除一些具有相同评论的规则 例如 我有带有 comment test it 的规则 所以我可以像这样获得它们的列表 sudo iptables t nat L grep test it 但是我怎样才能删除所有带有注释 测试它 的 PR

随机推荐

  • yum不能使用解决办法

    在安装完linux系统后 执行yum 发现报错 不能正常使用 解决方法如下 1 查看系统中是否有安装yum rpm qa grep yum 如果有返回 说明yum是安装了的 但还是不能正常使用 所以要卸载掉原来的yum 2 卸载yum rp
  • wget命令8种实用用法

    大家好 我是良许 wget 是一个可以从网络上下载文件的免费实用程序 它的工作原理是从 Internet 上获取数据 并将其保存到本地文件中或显示在你的终端上 这实际上也是大家所使用的浏览器所做的 例如 Firefox 或 Chrome 其
  • layer好看的弹出文本框

    layer open type 1 title 料架列表 skin layui layer rim 加上边框 area 300px 350px 宽高 shadeClose true skin yourclass content inLj c
  • 手写实现next_permutation(全排列)

    next permutation函数 需要加头文件
  • 绘制思维导图用什么软件?告诉你三个实用的软件

    思维导图是一种有效的思维模式 应用于记忆 学习 思考等的思维 地图 有利于人脑思维的扩散 如今市面上能够辅助我们更好地锻炼大脑 产出思维导图的工具数不胜数 但不同人群的使用不同 适配的软件也不尽相同 那么今天就让我来告诉你电脑好用的思维导图
  • 蚂蚁区块链第17课 错误码指导大全

    1 摘要 本文介绍蚂蚁区块链的错误码按出错来源分为5类 平台校验错误码 虚拟机错误码 区块链错误码 客户端系统错误码 TEE 错误码 并给出了具体的错误码值和解释说明 2 错误码大全 2 1 平台校验错误码 错误码 错误码值 错误消息 描述
  • [Django] Django基础环境配置

    step1 设置python 虚拟环境并激活 然后安装Django开发版本 这里可以本人参考博客 step2 新建项目 之前安装Django以及虚拟环境都是在C盘下处理的 在这里用D盘存储项目 出现小插曲 C Users 用户名 gt d
  • 2023高教社杯数学建模思路 - 案例:FPTree-频繁模式树算法

    文章目录 算法介绍 FP树表示法 构建FP树 实现代码 建模资料 赛题思路 赛题出来以后第一时间在CSDN分享 https blog csdn net dc sinor type blog 算法介绍 FP Tree算法全称是Frequent
  • MySQL基础篇-第15章_存储过程与函数

    第15章 存储过程与函数 讲师 尚硅谷 宋红康 江湖人称 康师傅 官网 http www atguigu com MySQL从5 0版本开始支持存储过程和函数 存储过程和函数能够将复杂的SQL逻辑封装在一起 应用程序无须关注存储过程和函数内
  • vue动态添加路由清空路由

    刚做的项目分多个模块 点击后再查询菜单 动态加进路由 直接动态添加则爆出警告信息 路由重复 于是乎想到了先清空路由 resetRouter const newRouter new Router mode hash scrollBehavio
  • TortoiseGit清除账号密码

    开发十年 就只剩下这套Java开发体系了 gt gt gt 1 编辑系统配置 2 删除配置信息 3 删除 git credentials 一般在c盘的用户目录下
  • pytorch怎么加入环境变量_pytorch安装(使用pip3装到conda环境下)(示例代码)

    之前在windows上使用pip3的方式安装过pytorch 虽然偶尔也会HTTP Error 安装失败 但是基本还是可以安装成功的 上 这一次在ubuntu上装了anaconda 想着之后的库都用conda安装 而不使用ubuntu自带的
  • 序(为什么要抄unreal源码)

    unreal所有源码很长 几百万行 一辈子也抄不完 然而 ue4 0版本的runtime只有1887个文件 251043行 不算第三方库 可以只按照渲染相关部分抄写一下 然后 逐版本增补 只需要关注渲染部分 和工作中用到的插件 还是可以的
  • 深入剖析Kubernetes之控制器模式的实现-Job与CronJob

    文章目录 Job CronJob Deployment StatefulSet 以及 DaemonSet 这三个编排概念 它们主要编排的对象 都是 在线业务 即 Long Running Task 长作业 比如 常用的 Nginx Tomc
  • 深度学习常见术语及作用--个人笔记

    1 池化层 提取重要信息 去掉不重要信息 减少参数 减少计算开销 防止过拟合 2 全连接层 FC 在整个卷积神经网络起 分类器 的作用 3 激活函数 给神经元引入了非线性因素 进而提升网络的表达能力 4 backbone 主干 骨干 网络
  • 快速查找Unity死循环

    我们先建立一个新工程 新建C 文件 然后在Start函数中加入以下代码 void Start while true int i 1 把这个C 文件挂到场景摄像机或其它GameObject上 打开这个工程对应的VS工程 如何用VS编辑unit
  • Spring DataBinding

    1 用 ModelAttribute注释方法 1 1 ModelAttribute和 RequestMapping同时注释一个方法 span style font size 14px RequestMapping method Reques
  • 送书

    六月 初夏 高考结束 毕业季到来 准大学生纠结选什么专业 毕业生迈进就业大军 不论什么身份 大家都在思考着同一件事情 当下什么能力最热门 想要得到答案很简单 打开任意一款求职软件 热门岗位的职位简介中都少不了这一项 数据分析能力 4月20日
  • 笔记&代码

    1 1数据与统计学 统计学的含义 数据及其分类和来源 1 1 1 什么是统计学 收集数据 数据分析 描述统计 利用图表 计算简单统计量 推断统计 根据样本判断总体 参数估计和假设检验 1 1 2 变量与数据 变量 数据 变量的观测结果就是数
  • TCP详解之重传机制

    TCP详解之重传机制 TCP 实现可靠传输的方式之一 是通过序列号与确认应答 在 TCP 中 当发送端的数据到达接收主机时 接收端主机会返回一个确认应答消息 表示已收到消息 但在错综复杂的网络 并不一定能如上图那么顺利能正常的数据传输 万一