[TCP/IP]可靠性

news/2024/11/15 20:03:23/文章来源:https://www.cnblogs.com/DCFV/p/18298513

重传机制

TCP 实现可靠传输的方式之一,是通过序列号与确认应答。在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个确认应答消息,表示已收到消息。
image
但在错综复杂的网络,并不一定能如上图那么顺利能正常的数据传输,万一数据在传输过程中丢失了呢?
所以 TCP 针对数据包丢失的情况,会用重传机制解决。
接下来说说常见的重传机制:

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

超时重传

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

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

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

我们先来了解一下什么是 RTT(Round-Trip Time 往返时延),从下图我们就可以知道:
image
超时重传时间是以 RTO (Retransmission Timeout 超时重传时间)表示。

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

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

当超时时间 RTO 较大时,重发就慢,丢了老半天才重发,没有效率,性能差;
当超时时间 RTO 较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
精确的测量超时时间 RTO 的值是非常重要的,这可让我们的重传机制更高效。

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

image

至此,可能大家觉得超时重传时间 RTO 的值计算,也不是很复杂嘛。
好像就是在发送端发包时记下 t0 ,然后接收端再把这个 ack 回来时再记一个 t1,于是 RTT = t1 – t0。没那么简单,这只是一个采样,不能代表普遍情况。
实际上「报文往返 RTT 的值」是经常变化的,因为我们的网络也是时常变化的。也就因为「报文往返 RTT 的值」 是经常波动变化的,所以「超时重传时间 RTO 的值」应该是一个动态变化的值。

Linux 是如何计算 RTO 的呢?

估计往返时间,通常需要采样以下两个:
需要 TCP 通过采样 RTT 的时间,然后进行加权平均,算出一个平滑 RTT 的值,而且这个值还是要不断变化的,因为网络状况不断地变化。
除了采样 RTT,还要采样 RTT 的波动范围,这样就避免如果 RTT 有一个大的波动的话,很难被发现的情况。
RFC6289 建议使用以下的公式计算 RTO:
image
其中 SRTT 是计算平滑的RTT ,DevRTR 是计算平滑的RTT 与 最新 RTT 的差距。
在 Linux 下,α = 0.125,β = 0.25, μ = 1,∂ = 4。别问怎么来的,问就是大量实验中调出来的。
如果超时重发的数据,再次超时的时候,又需要重传的时候,TCP 的策略是超时间隔加倍。
也就是每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。
超时触发重传存在的问题是,超时周期可能相对较长。那是不是可以有更快的方式呢?
于是就可以用「快速重传」机制来解决超时重发的时间等待。

快速重传

TCP 还有另外一种快速重传(Fast Retransmit)机制,它不以时间为驱动,而是以数据驱动重传。快速重传机制,是如何工作的呢?
image
在上图,发送方发出了 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 是接收方收到哪个报文而回复的,有可能是对Seq4、Seq5、Seq6的确认,也有可能是对Seq3、Seq4、Seq5的确认,那是选择重传 Seq2 一个报文,还是重传 Seq2 之后已发送的所有报文呢(Seq2、Seq3、 Seq4、Seq5、 Seq6) 呢?

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

可以看到,不管是重传一个报文,还是重传已发送的报文,都存在问题。
为了解决不知道该重传哪些 TCP 报文,于是就有 SACK 方法。

SACK 方法

还有一种实现重传机制的方式叫:SACK( Selective Acknowledgment), 选择性确认。
这种方式需要在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将已收到的数据的信息发送给「发送方」,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。
如下图,发送方收到了三次同样的 ACK 确认报文,于是就会触发快速重发机制,通过 SACK 信息发现只有 200~299 这段数据丢失,则重发时,就只选择了这个 TCP 段进行重复。
image
如果要支持 SACK,必须双方都要支持。在 Linux 下,可以通过 net.ipv4.tcp_sack 参数打开这个功能(Linux 2.4 后默认打开)。

Duplicate SACK

Duplicate SACK 又称 D-SACK,其主要使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。
下面举例两个栗子,来说明 D-SACK 的作用。

ACK 丢包

image

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

网络延时

image

数据包(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 后默认打开)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/742525.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零代码教你安装部署Stable Diffusion 3,一键生成高质量图像

Stable Diffusion 3的强大性能其实并不仅限于Diffusion Transformer在架构上所带来的增益,其在提示词、图像质量、文字拼写方面的能力都得到了极大的提升。本文分享自华为云社区《重磅!【支持中文】stable-diffusion-3安装部署教程-SD3 来了》,作者:码上开花_Lancer。 正如…

腾讯云服务器Centos7数据盘挂载

背景:新购进一台服务器,初始化磁盘50G,还剩余一个200G的数据盘未使用,现想将其挂在使用一、前置条件 1.已购买腾讯云服务器,并登录到服务器。 2.已创建一块数据盘。 3.已将数据盘格式化为文件系统并进行分区。 二、数据盘挂载流程 1.登录腾讯云官网,进入控制台,找到“云…

Microsoft SQL Server 2016 with SP3 GDR 发布,修复高危安全漏洞

Microsoft SQL Server 2016 with SP3 GDR 发布,修复高危安全漏洞Microsoft SQL Server 2016 with SP3 GDR 发布,修复高危安全漏洞 SQL Server Native Client OLE DB 提供程序远程代码执行漏洞 CVE-2024-35272 修复 请访问原文链接:https://sysin.org/blog/sql-server-2016/,…

hackmyvm--Decode

环境 靶机:ip未知 攻击机kali:192.168.233.128 192.168.56.101 主机探测 锁定靶机ip为108端口扫描 nmap -p- -T4 -A 192.168.56.108常规套路80和22 web打点 dirsearch -u http://192.168.56.108/访问robots,txt文件访问/decode发现其自动添加了/,怀疑是本地文件包含漏洞,即可…

面试前:各方面都匹配 面试后:恐怕是凉了

在求职过程中,面试是一个至关重要的环节。许多求职者在简历筛选阶段表现出色,但在面试中却屡屡受挫。为了帮助大家更好地准备面试,本文分享了一位粉丝的QQ面试经验,涵盖了从自我介绍到技术问题的各个方面。很多人在浏览简历信息时觉得自己的条件很符合某家公司的要求,但一…

微信小程序车牌键盘输入组件(支持单个删除更改,支持赋值,支持新能源)

网上一搜一大堆类似但大多都相对简单,适用的场景并不多。多数也不支持赋值 不支持单个删除更改 我就借鉴了以下文章的思路,为了达到自己想要的效果做了相对应的更改。 借鉴文章链接:> https://blog.csdn.net/qq706352062/article/details/105554453?ops_request_misc=%…

ARC算法实现

1. 概述 Adaptive Replacement Cache(ARC)是一种缓存替换算法,用于提高缓存的命中率。ARC 动态调整缓存策略,以适应实际的访问模式,从而在不确定的工作负载下表现良好。它通过同时维护两个缓存列表来追踪最近使用和频繁使用的数据块,并根据访问模式在这两个列表之间动态分…

西瓜种类与挑选方法

感觉十分有用,留存一下 转载自微信公众号:科技da表哥 西瓜种类如何挑选西瓜

阿里云oss配置:

一,创建bucket bucket是,存储空间是OSS的全局命名空间,相当于数据的容器,可以存储若干文件。点 完成创建 按钮 二,创建账号供访问oss资源创建用户成功后,把accesskey id和accesskey secret复制保存下来三,创建对bucket的访问策略最后点击 确定 按钮创建

Lua调用C的函数

#include <iostream> #include <string> using namespace std;extern "C" {#include "lua.h"#include "lualib.h"#include "lauxlib.h" }int myTest(lua_State* L) {// 获得Lua函数的参数的数量int nArgs = lua_gettop(L)…

如何强制删除文件夹

前几天下载了ZeroTier,不知道是哪里出问题了,手动删除文件夹一直不成功,一直提示“你需要xxx权限才能删除改文件夹”,就算我修改了文件夹所有者有无济于事,在网上找了很多方法都没用,比如说“shift+del”,还是会提示我权限不够 后面找到一个方法终于解决了 每次删文件都提…

pdf.js源码分析-字体加载流程

pdf.js中的字体加载流程,下面演示一种Type1的字体的加载流程,会把一些兼容性的内容省去,只记录字体数据的加载过程中涉及到的方法和作用:evaluator.js -> handleSetFont:操作符列表中加载字体 evaluator.js -> loadFont:加载字体的方法 evaluator.js -> preEval…