42、可靠传输——连续ARQ

news2024/10/7 10:25:24

上回内容我们学习到,一种保证可靠传输的机制——ARQ协议,ARQ协议通过设置超时定时器,当在规定时间内没有收到来自对方发来的“确认”报文,就自动报文重传。这其中,ARQ协议和停止等待机制的结合,我们把它称作“停等ARQ”,发送完一个报文之后必须等待对方的确认才能继续发送下一个报文。

由此可见,停等ARQ虽然可以一定程度上保证可靠传输,而且实现起来比较简单,但是由于其“停止等待”的特点,导致使用这种机制的通信,信道利用率太低

因为一个报文发送出去之后,距离下一个报文的发送,至少要经过一个端到端的往返时间(也就是一个RTT,因为发送报文到达接收端以后,还要再等对方“确认”报文再回来),此外再加上一些接收端处理报文的时间,发送端处理“确认报文”的时间、出现问题再重传的时间等等这些,导致在整个通信过程中,“真正报文”发送的时间只占一小部分,整个信道的利用率就变得非常低。

因此为了解决这个利用率的问题,后来就借鉴了“流水线思想”,让发送方可以连续发送多个报文,而不必每发送完一个报文就停下来等待对方确认,这样可以做到信道上一直有数据在传输,提高其利用率。(如要具体了解流水线,可查阅计算机组成原理课程中“CPU流水线技术”)

将“流水线”思想结合到ARQ协议,同时还要结合滑动窗口技术来实现,就是本节内容要学习的连续ARQ方式


滑动窗口

滑动窗口,是一种流量控制技术,同时也是TCP协议的精髓所在,后面还会学习到TCP的流量控制,也是用滑动窗口来实现的。

依照惯例,我们在学习一个新概念的时候,首先知道它是什么,然后需要知道它为什么。也就是知道了滑动窗口是一种流量控制技术之后,下一步我们要做的就是它为什么会叫这个名字。关于这个问题,这就要说到它的本质了,滑动窗口的本质其实就是数组的双指针,数组就是窗口,指针可以用来滑动(若详细了解数组和指针,可学习数据结构的知识),在这里我们可以简单的把存放报文的缓冲区当作窗口,把发送方主机的缓冲区叫做“发送窗口”,把接收方主机的缓冲区叫做“接收窗口”

刚才我们说过,连续ARQ方式是要结合滑动窗口技术来实现的,就是要做到可以连续发送多个报文,而不必发送完一个就要停下来等待。这也就意味着,在发送窗口中能够容纳多个报文,然后可以连续的把报文发送出去,同时收到对一个报文的“确认”后,窗口还要向前滑动。

谢希仁老师教材上给出的例图,可以很好地解释这个过程:

该图中展示了一个可以容纳五个报文的发送窗口(图中的数字序号就是报文的编号),所以这个发送窗口的大小就是 5 。这五个报文可以连续的发送出去。在收到接收方对报文 1 的确认后,发送窗口自动向前滑动,把报文 6 “扩进来”。后面的报文以此类推。

在这里还需要注意一点的是,仍然要为每一个报文设置一个超时定时器,在时间到之前没有收到对方发来的确认,就要重传该报文。不过,连续ARQ和停等ARQ,关于接收端对报文的确认方式,是有不同的

停等ARQ中,发送方必须要等着接收端对一个报文的确认才能继续发送后面的;

而在连续ARQ中由于发送方可以连续发送,所以也不要求接收方对收到的每一个报文都进行确认,接收方一般可以“累积确认”,也就是在收到几个报文后,对按序到达的最后一个报文发送确认即可,这就表示告诉发送方:到这个报文为止的所有报文都正确收到了。就比如,发送方正在发送第四个报文的时候,收到了来自接收方对报文 3 的确认,那么发送方也就知道前面的1、2、3号报文都已被正确接收。

可见,接收方使用这种“累积确认”,也可以一定程度上提升通信效率。但同时也应注意的是,使用累积确认方式,最关键的一点是:报文是必须按序到达的如果不是按序到达,那么接收方将会在“断点处”发送确认,而不是对最后一个报文发送确认。举个例子就是:如果发送方把五个报文都已经发送出去了,但其中的 3 号报文在传输中丢失了,接收方只收到了1、2、4、5号报文,这时候由于没有收到 3 号,那么接收方将会发出对 2 号报文的确认,告诉接收方 1 号和 2 号报文正确收到了。这时候,发送方对 3 号报文重传,可以有两种重传的方式,这两种方式有些区别,下面我们依次学习:


选择重传(SR)

“选择重传”的特点是:接收方收到一个确认一个,发送方只需要重传出错的报文。

拿上面的例子来说,只有 3 号报文丢失了(或者是出了差错),那么接收方将会把1、2、4、5号报文暂时都缓存起来,然后向发送方挨个发出确认。这样的话,发送方就能很清楚的知道 3 号报文出了错,所以重传 3 号报文。

由此可见,如果发送方重传报文的方式,使用“选择重传”的话,那么需要接收方要有一定的缓存能力,并且要求接收方能够对“失序”的报文进行缓存。


回退N(GBN)

还有一种重传的方式,叫做回退N方式,全称“ go back  N ”,也可简称“GBN”。这种方式的特点是:接收方只对“顺序到达”的报文进行确认,发送方要把出错报文的后续全部报文都进行重传

还是上面的例子,使用GBN的话,接收方收到了1、2、4、5号报文,但是由于不是按序到达,所以接收方将会丢弃4、5号报文,只会发出对 2 号报文的确认,以告诉发送方到2号为止的所有报文都收到了。这时候的发送方将会对3、4、5号报文都进行重传。


到这里为止,我们学习就完了关于ARQ协议保证可靠传输的一个工作原理,这将对后面学习TCP协议的可靠传输机制打下基础。同时在这过程中,也学习到了一些其它的知识点,比如滑动窗口,这都是TCP后续学习中非常重要的知识基础。从下一节开始,我们将正式学习TCP协议具体的内容。

参考教材:谢希仁《计算机网络》第八版

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

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

相关文章

USB PD快充保护方案有哪些?用集成式TVS还是分立式TVS?

USB Power Delivery ,简称USB PD,是由USB-IF组织制定的一种快速充电规范,目前主流的快充协议之一。该规范可实现更高的电压和电流,输送的功率最高可达100瓦,并可以自由的改变电力的输送方向。在日常使用USB PD快充充电…

CNN卷积详解(三)

一、卷积层的计算 4 ∗ * ∗ 4的输入矩阵 I I I 和 3 ∗ * ∗ 3 的卷积核 K K K: 在步长(stride)为 1 时,输出的大小为 ( 4 − 3 1 ) ( 4 − 3 1) 计算公式: ● 输入图片矩阵 I I I 大小: w w w w ww ●…

【八大排序】-- 基数排序(动图演示)

基数排序(桶排序)介绍 (1)基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是通…

【环境配置】Windows10-YOLOv8运行报错

问题如下: Windows10 运行 YOLOv8 出现如下错误: Traceback (most recent call last): File “”, line 1, in File “D:\anaconda3\envs\yolov8\Lib\multiprocessing\spawn.py”, line 116, in spawn_main exitcode _main(fd, parent_sentinel) ^^^^^…

【ROS】话题通信--从理论介绍到模型实现

1.简单介绍 话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。像雷达、摄像头、GPS… 等等一些传感器数据的采集,也都是使用了话题通信,换言之…

帆软大屏2.0企业制作

 数字化观点中心 / 当前页 如何从0-1制作数据大屏,我用大白话给你解释清楚了 文 | 商业智能BI相关文章 阅读次数:18,192 次浏览 2023-06-08 11:51:49 好莱坞大片《摩天营救》中有这么一个场景:  你可以看见反派大b…

设备数字化平台的优势和应用价值

在现代工业领域,设备的高效管理和维护对于企业的运营和竞争力至关重要。而设备管理系统作为一个强大的工具,可以极大地提升设备管理和维护的效率,从而实现生产效益的最大化。本文将探讨设备数字化平台的优势和应用价值。 设备数字化平台是一款…

蓝桥杯嵌入式省一教程:(一)点亮LED

如同所有编程入门的第一个教程——打印"Hello world"一样,点亮LED可以算得上是嵌入式开发中的"Hello world",所有的单片机开发入门都从这里开始。 在点亮LED前,我们需要先了解一个重要概念——GPIO(General Purpose Inp…

【C++】queue容器

1.queue容器基本概念 2.queue常用接口 #include <iostream> using namespace std;//队列queue #include<queue>//创建Person类 class Person { public:Person(string name, int age){this->m_Name name;this->m_Age age;}string m_Name; //姓名int m_Age; …

【hive】hive中row_number() rank() dense_rank()的用法

hive中row_number() rank() dense_rank()的用法 一、函数说明 主要是配合over()窗口函数来使用的&#xff0c;通过over(partition by order by )来反映统计值的记录。 rank() over()是跳跃排序&#xff0c;有两个第二名时接下来就是第四名(同样是在各个分组内)dense_rank() …

04-分支语句和逻辑运算符

分支语句和逻辑运算符 6.1、if语句 if 结构 例子 统计输入的字符数、空格数 // if.cpp -- using the if statement #include <iostream> int main() {using std::cin; // using declarationsusing std::cout;char ch;int spaces 0;int total 0;cin.get(ch);wh…

mysql数据库设置创建时间和更新时间自动更新

1、创建时间&#xff1a;CURRENT_TIMESTAMP 2、修改时间&#xff1a;ON UPDATE CURRENT_TIMESTAMP DROP TABLE IF EXISTS mall_pay_info; CREATE TABLE mall_pay_info (id int(11) NOT NULL AUTO_INCREMENT,user_id int(11) DEFAULT NULL COMMENT 用户id,order_no bigint(20)…

IS3DH加速度计使用SPI和IIC方式读取数据LIS3DH中英文文档和测试代码

最近博主在研究一款低功耗加速度计LIS3DH&#xff0c;该加速度计有两种通信模式&#xff0c;IIC和SPI方式。IIC通信方式搞了一下 就好了&#xff0c;但是SPI方式针扎了两天才做出来&#xff0c;现在和大家分享一下心得。 开发环境&#xff1a;MDK keil5 使用芯片&#xff1a…

Centos7 配置Docker镜像加速器

daemon.json 文档说明&#xff1a; docker安装后默认没有daemon.json这个配置文件&#xff0c;需要进行手动创建&#xff0c;docker不管是在哪个平台以何种方式启动, 默认都会来这里读取配置,使用户可以统一管理不同系统下的 docker daemon 配置。 如果在daemon.json文件中进行…

Syncfusion Essential Studio JavaScrip Crack

Syncfusion Essential Studio JavaScrip Crack 数据透视表 添加了在将数据透视表导出到PDF文档时自定义列宽的支持。 签名 添加了对在特定位置绘制文本的支持。 Syncfusion Essential Studio for JavaScript在一个包中包含80多个高性能、轻量级、模块化和响应式UI组件。包括Jav…

Memory Allocators 101 - Write a simple memory allocator

Memory Allocators 101 - Write a simple memory allocator - Arjun Sreedharan BlogAboutContactPosts GoogleLinkedInGithubFacebookTwitterUMass Amherst 1:11 AM 9th 八月 20160 notes Memory Allocators 101 - Write a simple memory allocator Code related to this…

数据结构——B-树、B+树、B*树

一、B-树 1. B-树概念 B树是一种适合外查找的、平衡的多叉树。一棵m阶&#xff08;m>2&#xff09;的B树&#xff0c;是一棵平衡的M路平衡搜索树&#xff0c;它可以是空树或满足以下性质&#xff1a; &#xff08;1&#xff09;根节点至少有两个孩子。 &#xff08;2&#…

Integer中缓存池讲解

文章目录 一、简介二、实现原理三、修改缓存范围 一、简介 Integer缓存池是一种优化技术&#xff0c;用于提高整数对象的重用和性能。在Java中&#xff0c;对于整数值在 -128 到 127 之间的整数对象&#xff0c;会被放入缓存池中&#xff0c;以便重复使用。这是因为在这个范围…

UDP 的报文结构以及注意事项

UDP协议 1.UDP协议端格式 1.图中的16位UDP长度,表示整个数据报(UDP首部UDP数据)的最大长度 2.若校验和出错,会直接丢弃 2.UDP的报文结构 UDP报文主体分为两个部分:UDP报头(占8个字节)UDP载荷/UDP数据 1.源端口号 16位,2个字节 2.目的端口号 16位,2个字节 3.包长度 指示了…

laravel框架中批量更新数据

在php框架中 tp中就有批量更新封装好的 SaveAll 在laravel中有批量插入没有批量更新操作;因此我们可以自己去封装一个 然后批量进行更新操作 封装参考代码: /*** 批量更新** param $tableName 表名称* param string $pk 更新的字段* param array $multipleData 要更新的数据*…