【运输层】TCP 的可靠传输是如何实现的?

news2024/12/28 4:05:34

目录

1、发送和接收窗口(滑动窗口)

(1)滑动窗口的工作流程

(2)滑动窗口和缓存的关系

(3)滑动窗口的注意事项

2、如何选择超时重传时间

(1)加权平均往返时间 RTTs

(2)Karn 算法

3、选择确认 SACK


1、发送和接收窗口(滑动窗口)

        TCP 的滑动窗口是以字节为单位的。

(1)滑动窗口的工作流程

        现假定 A 收到了 B 发来的确认报文段,其中窗口是 20 字节,而确认号是 31(这表明 B 期望收到的下一个字节序号是 31,而到序号 30 为止的数据已经收到了)。根据这两个数据,A 就构造出自己的发送窗口,如下图所示://发送窗口

        上图所示为 A 的发送窗口,发送窗口表示:在没有收到 B 的确认的情况下,A 可以连续把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。

        发送窗口里面的序号表示允许发送的序号。显然,窗口越大,发送方就可以在收到对方确认之前连续发送更多的数据,因而可能获得更高的传输效率。接收方会把自己的接收窗口数值放在窗口字段中发送给对方。因此,A 的发送窗口一定不能超过 B 的接收窗口数值

        发送窗口后沿的后面部分表示已发送且已收到了确认。这些数据显然不需要再保留了。而发送窗口前沿的前面部分表示不允许发送,因为接收方没有为这部分数据保留临时存放的缓存空间。//发送窗口的位置由窗口前沿和后沿的位置共同确定

        现在假定 A 发送了序号为 31~41 的数据。这时,发送窗口位置并未改变,但发送窗口内靠后面有 11 个字节(灰色方框表示)表示已发送但未收到确认。而发送窗口内靠前面的 9 个字节(序号 42~50)是允许发送但尚未发送的。//发送窗口发送数据

        再看一下 B 的接收窗口。设 B 的接收窗口大小是 20。在接收窗口外面,到序号为 30 的数据是已经发送过确认,并且已经交付主机了。因此在 B 可以不再保留这些数据。//接收窗口

        接收窗口内的数据(序号31~50)是允许接收的。如上图所示,B 收到了序号为 32 和 33 的数据,但序号为 31 的数据没有收到(也许丢失了,也许滞留在网络中的某处)。请注意,B 只能对按序收到的数据中的最高序号给出确认,因此 B 发送的确认报文段中的确认号仍然是 31(即期望收到的序号)。

        现在假定 B 收到了序号为 31 的数据,把序号为 31~33 的数据交付主机,删除这些数据。接着把接收窗口向前移动 3 个序号,如下图所示,同时给 A 发送确认,其中窗口值仍为 20,但确认号是 34。这表明 B 已经收到了到序号 33 为止的数据。//接收窗口接收数据

        我们注意到,B 还收到了序号为 37,38 和 40 的数据,但这些数据都没有按序到达,只能先暂存在接收窗口中。A 收到 B 的确认后,就可以把发送窗口向前滑动 3 个序号,但指针 P_{2_{}} 不动。可以看出,现在 A 的可用窗口增大了些,可发送的序号范围是 42~53。//窗口移动

        A 在继续发送完序号 42~53 的数据后,指针 P_{2} 向前移动和 P_{3} 重合。

        此时,发送窗口内的序号都已用完,但还没有再收到确认。由于 A 的发送窗口已满,可用窗口已减小到零,因此必须停止发送

        请注意,存在下面这种可能性,就是发送窗口内所有的数据都已正确到达 B,B 也早已发出了确认。但不幸的是,所有这些确认都滞留在网络中。在没有收到 B 的确认时,为了保证可靠传输,A 只能认为 B 还没有收到这些数据。于是,A 在经过一段时间后(由超时计时器控制)就重传这部分数据,重新设置超时计时器,直到收到 B 的确认为止。如果 A 按序收到落在发送窗口内的确认号,那么 A 就可以使发送窗口继续向前滑动,并发送新的数据。//此时可能会发生消息重传

(2)滑动窗口和缓存的关系

        上边过程中,提到了缓存,那么窗口和缓存有什么关系呢?

        这个关系就是:发送方的应用进程会把字节流写入 TCP 的发送缓存,接收方的应用进程从 TCP 的接收缓存中读取字节流。

        发送窗口和发送缓存:

        发送缓存用来暂时存放:

  1. 发送应用程序传送给发送方 TCP 准备发送的数据
  2. TCP 已发送出但尚未收到确认的数据

        发送窗口通常只是发送缓存的一部分。已被确认的数据应当从发送缓存中删除,因此发送缓存和发送窗口的后沿是重合的。发送应用程序最后写入发送缓存的字节减去最后被确认的字节,就是还保留在发送缓存中的被写入的字节数。发送应用程序必须控制写入缓存的速率,不能太快,否则发送缓存就会没有存放数据的空间。

        接收窗口和接收缓存:

        接收缓存用来暂时存放:

  1. 按序到达的、但尚未被接收应用程序读取的数据
  2. 未按序到达的数据

        如果收到的分组被检测出有差错,则要丢弃。如果接收应用程序来不及读取收到的数据,接收缓存最终就会被填满,使接收窗口减小到零。反之,如果接收应用程序能够及时从接收缓存中读取收到的数据,接收窗口就可以增大,但最大不能超过接收缓存的大小。

(3)滑动窗口的注意事项

        第一,虽然 A 的发送窗口是根据 B 的接收窗口设置的,但在同一时刻,A 的发送窗口并不总是和 B 的接收窗口一样大。这是因为通过网络传送窗口值需要经历一定的时间滞后(这个时间是不确定的)。另外,发送方 A 还可能根据网络当时的拥塞情况适当减小自己的发送窗口数值。

        第二,对于不按序到达的数据应如何处理,TCP 标准并无明确规定。如果接收方把不按序到达的数据一律丢弃,那么接收窗口的管理将会比较简单,但这样做对网络资源的利用不利(因为发送方会重复传送较多的数据)。因此 TCP 通常是把不按序到达的数据先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程

        第三,TCP 要求接收方必须有累积确认的功能,这样可以减小传输开销。接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。但请注意两点。一是接收方不应过分推迟发送确认,否则会导致发送方不必要的重传,这反而浪费了网络的资源。TCP 标准规定,确认推迟的时间不应超过 0.5 秒。若收到一连串具有最大长度的报文段,则必须每隔一个报文段就发送一个确认。二是捎带确认实际上并不经常发生,因为大多数应用程序很少同时在两个方向上发送数据。

        此外,TCP 的通信是全双工通信。通信中的每一方都在发送和接收报文段。因此,每一方都有自己的发送窗口和接收窗口。

2、如何选择超时重传时间

        为什么说选择超时重传时间是 TCP 最复杂的问题之一呢?

        由于 TCP 的下层是互联网环境,发送的报文段可能只经过一个高速率的局域网,也可能经过多个低速率的网络,并且每个 IP 数据报所选择的路由还可能不同。如果把超时重传时间设置得太短,就会引起很多报文段的不必要的重传,使网络负荷增大。但若把超时重传时间设置得过长,则又使网络的空闲时间增大,降低了传输效率。

        那么,运输层的超时计时器的超时重传时间究竟应设置为多大呢?

(1)加权平均往返时间 RTTs

        TCP 采用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间。这两个时间之差就是报文段的往返时间 RTT。TCP 保留了 RTT 的一个加权平均往返时间 RTTs(这又称为平滑的往返时间,S 表示 Smoothed)。每当第一次测量到 RTT 样本时,RTTs 值就取为所测量到的 RTT 样本值。以后每测量到一个新的 RTT 样本,就按下式重新计算一次 RTTs:

        新的RTTs = (1 - \alpha)* (旧的RTTs)+ \alpha *(新的RTT样本)

  • 其中,0\leq \alpha < 1
  • 若 \alpha \rightarrow 0,表示 RTT 值更新较慢
  • 若 \alpha \rightarrow 1表示 RTT 值更新较快
  • RFC 6298 推荐的 \alpha 值为 1/8,即 0.125

        显然,超时计时器设置的超时重传时间 RTO (RetransmissionTime-Out) 应略大于上面得出的加权平均往返时间 RTTs。RFC 6298 建议使用下式计算 RTO:

        RTO = RTTs + 4 * RTT_{D}

        而 RTT_{D} 是 RTT 的偏差的加权平均值,它与 RTTs 和新的 RTT 样本之差有关。当第一次测量时,RTT_{D} 值取为测量到的 RTT 样本值的一半。在以后的测量中,则使用下式计算加权平均的RTT_{D} :

        新的RTT_{D} = (1 - \beta)* (旧的RTT_{D})+ \beta * | RTTs - 新的RTT样本 |

        这里 \beta 是个小于 1 的系数,它的推荐值是 1/4,即 0.25。

        //这些公式看起来多,实际上理解并不复杂,就是在 RTT 的加权平均值上做了一点点改动而已

        上面所说的往返时间的测量方法理解起来很简单,但实现起来却相当复杂。

        如下图所示,发送出一个报文段,设定的重传时间到了,还没有收到确认,于是重传报文段。经过了一段时间后,收到了确认报文段。

        现在的问题是:如何判定此确认报文段是对先发送的报文段的确认,还是对后来重传的报文段的确认呢?

        由于重传的报文段和原来的报文段完全一样,因此源主机在收到确认后,就无法做出正确的判断,而正确的判断对确定加权平均 RTTs 的值关系很大。

困惑的问题:重传确认影响重传时间 RTO计算不准确

        若收到的确认是对重传报文段的确认,但却被源主机当成是对原来的报文段的确认,则这样计算出的 RTTs 和超时重传时间 RTO 就会偏大。若后面再发送的报文段又是经过重传后才收到确认报文段,则按此方法得出的超时重传时间 RTO 就越来越长。

        同样,若收到的确认是对原来的报文段的确认,但被当成是对重传报文段的确认,则由此计算出的 RTTs 和 RTO 都会偏小。这就必然导致报文段过多地重传。这样就有可能使 RTO 越来越短。

(2)Karn 算法

        根据以上所述,Karn 提出了一个算法:在计算加权平均 RTTs 时,只要报文段重传了,就不采用其往返时间样本。这样得出的加权平均 RTTs 和 RTO 就较准确//Karn算法

        但是,这又引起新的问题。设想出现这样的情况:报文段的时延突然增大了很多。因此在原来得出的重传时间内不会收到确认报文段,于是就重传报文段。但根据 Karn 算法,不考虑重传的报文段的往返时间样本。这样,超时重传时间就无法更新。

可借鉴的思想和改进:

        因此要对 Karn 算法进行修正。方法是:报文段每重传一次,就把超时重传时间 RTO 增大一些。典型的做法是取新的重传时间为旧的重传时间的 2 倍。当不再发生报文段的重传时,才根据上面给出的计算公式计算超时重传时间。

        所以,Karn 算法能够使运输层区分开有效的和无效的往返时间样本,从而改进了往返时间的估测,使计算结果更加合理。

3、选择确认 SACK

        若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经正确到达接收方的数据呢?

        答案是可以的。选择确认(Selective ACK) 就是一种可行的处理方法。

        下边用一个例子来说明选择确认的工作原理。

        TCP 的接收方在接收对方发送过来的数据字节流的序号不连续,结果就形成了一些不连续的字节块。下图中,序号 1~1000 收到了,但序号 1001 ~1500 没有收到。接下来的字节流又收到了,可是又缺少了 3001 ~ 3500。再后面从序号 4501 起又没有收到。也就是说,接收方收到了和前面的字节流不连续的两个字节块。

        如果这些字节的序号都在接收窗口之内,那么接收方就先收下这些数据,但要把这些信息准确地告诉发送方,使发送方不要再重复发送这些已收到的数据。//解决问题的思路

        从上图可看出,和前后字节不连续的每一个字节块都有两个边界:左边界和右边界,因此在图中用四个指针标记这些边界。请注意,第一个字节块的左边界 L1 = 1501,但右边界 R1 = 3001 而不是 3000。这就是说,左边界指出字节块的第一个字节的序号,但右边界减 1 才是字节块的最后一个序号。

        我们知道,TCP 的首部没有哪个字段能够提供上述这些字节块的边界信息。RFC 2018规定,如果要使用选择确认 SACK,那么在建立 TCP 连接时,就要在 TCP 首部的选项中加上“允许SACK”的选项,而双方必须都事先商定好。如果使用选择确认,那么原来首部中的“确认号字段”的用法仍然不变。只是以后在 TCP 报文段的首部中都增加了 SACK 选项,以便报告收到的不连续的字节块的边界。//设置SACK的值时需要考虑TCP首部选项的长度的限制

        然而,SACK 文档并没有指明发送方应当怎样响应 SACK。因此大多数的实现还是重传所有未被确认的数据块。//所以,你知道TCP进行选择确认的具体实现方案吗?如果有,请分享给我,谢谢

        至此,全文结束。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React面试

React渲染流程(重点) jsx描述界面 jsx babel render function>vdom vdom fiber 在进行渲染 vdom 转换fiber reconcile 转换过程创建dom commit 到domvdom React Element 对象, 只记录了子节点, 没有记录兄弟节点, 因为渲染不可中断 fiber fiberNode 对象, 是一个链表 父节…

lua学习笔记13(一些特殊用法的学习和三目运算符的实现)

print("*****************************一些特殊用法的学习*******************************") print("*****************************多变量赋值*******************************") local a,b,c114514,8848,"凌少" print(a) print(b) print(c) -…

C#操作MySQL从入门到精通(7)——对查询数据进行简单过滤

前言 我们在查询数据库中数据的时候,有时候需要剔除一些我们不想要的数据,这时候就需要对数据进行过滤,比如学生信息中,我只需要年龄等于18的,类似这种操作,本文就是详细介绍如何对查询的数据进行初步的过滤。 1、等于操作符 本次查询student_age 等于20的数据,使用我…

导出加入域控的电脑清单

要导出加入域控的所有电脑清单&#xff0c;包括计算机名等基本信息&#xff0c;可以使用 PowerShell 中的 Get-ADComputer cmdlet。下面是一个基础示例脚本&#xff0c;用于从Active Directory (AD)中批量导出所有加入域的计算机名称及可能的其他相关信息&#xff0c;并将其保存…

Mudbus协议CRC校验码C#

Mudbus协议CRC校验码C# 什么是modbus协议特点协议格式modbus-crc16校验原理方法帧校验CRC计算方法&#xff1a;例子 C#代码Demo源码下载 什么是modbus Modbus是一种串行通信协议&#xff0c;最初由Modicon&#xff08;目前属于施耐德电气公司&#xff09;于1979年开发 Modbus协…

设计模式之访问者模式讲解

概念&#xff1a;封装一些作用于某种数据结构中的各元素的操作&#xff0c;它可以在不改变数据结构的前提下定义作用于这些元素的新操作。 抽象访问者&#xff1a;声明一个或多个访问操作&#xff0c;定义访问者可以访问哪些元素。具体访问者&#xff1a;实现抽象访问者的所有操…

2-4 AUTOSAR ASW Port端口

返回总目录->返回总目录<- 一、端口Port 软件组件的端口根据输入/输出方向可分为需型端口(Require Port,RPort)与供型端口(Provide Port,PPort),以及供需端口(Provide and Require Port,PRPort)。 需型端口可以和供型端口连接。 需型端口:用于从其他软件组件获…

多线程原理详解01(程序、进程、线程介绍,线程创建的三种方式(Thread、Runnable、Callable)、三种方式各自实现多线程的具体操作、代码解析)

目录 多线程原理详解01_线程简介多任务多线程程序、进程、线程Process&#xff08;进程&#xff09;与 Thread &#xff08;线程&#xff09;总结&#xff1a; 02_线程创建三种方式&#xff1a;1、继承 Thread 类1-1&#xff1a;通过继承Thread类实现多线程演示代码 1-2&#x…

干货分享 | 在TSMaster中加载基于DotNet平台的SeedKey

在UDS诊断过程中&#xff0c;会涉及到安全访问的问题&#xff0c;也就是所谓的Seed&Key。TSMaster 诊断模块支持通过.dll文件载入 Seed&Key 算法用于安全访问解锁。在最近发布的TSMaster 2024.03版本中不仅支持了C/C&#xff0c;Delphi等语言封装的DLL文件&#xff0c;…

基于GD32的简易数字示波器(3)- PCB设计

这期记录的是项目实战&#xff0c;做一个简易的数字示波器。 教程来源于嘉立创&#xff0c; 本期介绍PCB设计的大致流程。 下图为示波器的指标 具有选择交流耦合还是直流耦合功能、输入信号不衰减或衰减50倍 输入频率理论最大800KHz输入幅值&#xff08;不衰减&#xff09;…

【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(四)- 配置和设置指令(vsetvli/vsetivli/vsetvl)

1. 引言 以下是《riscv-v-spec-1.0.pdf》文档的关键内容&#xff1a; 这是一份关于向量扩展的详细技术文档&#xff0c;内容覆盖了向量指令集的多个关键方面&#xff0c;如向量寄存器状态映射、向量指令格式、向量加载和存储操作、向量内存对齐约束、向量内存一致性模型、向量…

SUSE Linux Enterprise Server安装

1. SUSE镜像下载 下载地址&#xff1a;Evaluation Copy of SUSE Linux Enterprise Server | SUSE 选择自己需要的版本和对应的架构 选择下载SLE-15-SP5-Full-x86_64-GM-Media1.iso&#xff0c;下载时需要注册请按照提示进行注册。 2. 安装SUSE Linux 安装时可以通过连接服务…

MySQL高级(索引结构Hash,为什么InnoDB存储引擎选择使用B+tree索引结构?)

目录 1、Hash索引结构 2、Hash索引特点 3、存储引擎支持 4、为什么InnoDB存储引擎选择使用Btree索引结构&#xff1f; 1、Hash索引结构 哈希索引就是采用一定的hash算法&#xff0c;将键值换算成新的hash值&#xff0c;映射到对应的槽位上&#xff0c;然后存储在hash表中。 如…

希尔排序解读

在算法世界中&#xff0c;排序算法是至关重要的一部分。而希尔排序&#xff08;Shell Sort&#xff09;作为一种基于插入排序的改进算法&#xff0c;通过允许交换非相邻元素&#xff0c;从而在一定程度上提高了排序效率。本文将深入探讨希尔排序的原理、实现方式以及它的性能特…

电商技术揭秘十五:数据挖掘与用户行为分析

相关系列文章 电商技术揭秘一&#xff1a;电商架构设计与核心技术 电商技术揭秘二&#xff1a;电商平台推荐系统的实现与优化 电商技术揭秘三&#xff1a;电商平台的支付与结算系统 电商技术揭秘四&#xff1a;电商平台的物流管理系统 电商技术揭秘五&#xff1a;电商平台…

【3GPP】【核心网】核心网/蜂窝网络重点知识面试题一(超详细)

目录 1. 核心网技术演进、各大运营商采用的技术是什么&#xff1f; 2. 整体掌握lte网络架构&#xff0c;能画出网络拓扑&#xff0c;并指出关键接口的位置 3. 对于主要的LTE核心网网元&#xff0c;讲讲自己对其功能的理解 4. 核心网常用字段概念&#xff1a;imsi、msisdn、…

Python学习从0到1 day21 第二阶段 面向对象 ④ 类型注解

仗剑红尘已是癫&#xff0c;有酒平步上青天 —— 24.4.7 一、变量的类型注解 学习目标 1.理解为什么使用类型注解 2.掌握变量的类型注解语法 为什么使用类型注解 tip&#xff1a;CTRLP&#xff0c;可以提示函数中传入的参数 当我们需要使用pycharm的自动补全功能&#xff0c;又…

论如何在小程序展示超链接在线网页

在工作中遇到一个需求&#xff0c;就是在小程序中展示超链接网页&#xff0c;起初我是直接使用web-view标签 <web-view src"https://www.baidu.com/"/>但是web-view只能在开发阶段手机上展示&#xff0c;一旦小程序发布线上&#xff0c;就会出现下面这种情况“…

Unity类银河恶魔城学习记录12-7-2 p129 Craft UI - part 2源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_CraftWindow.cs using UnityEngine.UI; using TMPro; using UnityEngin…

如何通过跨网软件,实现网络隔离后的文件安全收发摆渡?

随着企业数字化转型的逐步深入&#xff0c;企业投入了大量资源进行信息系统建设&#xff0c;信息化程度日益提升。绝大多数企业为了防止内部核心数据泄露&#xff0c;会实施网络隔离&#xff0c;比如内外网隔离&#xff0c;或者在内部网络中又划分出研发网、办公网、生产网等。…