计算机网络 | 谈谈TCP的流量控制与拥塞控制
文章目录
- 一、TCP的流量控制
- 1、利用滑动窗口实现流量控制【⭐⭐⭐】
- 2、如何破解【死锁】局面❓
- 二、TCP的拥塞控制
- 1、拥塞控制的一般原理
- ① 解决网络拥塞的误区
- ② 拥塞控制与流量控制的关系【重点理解✔】
- 2、TCP的拥塞控制方法
- ① 接收窗口【rwnd】与拥塞窗口【cwnd】
- ② 慢开始和拥塞避免算法
- ③ 快重传和快恢复算法
- 三、总结与提炼
一、TCP的流量控制
1、利用滑动窗口实现流量控制【⭐⭐⭐】
对于滑动窗口,在上面也提到过了,在流量控制这一块,就要利用到这个滑动窗口的机制去实现两个主机之间的通信
[流量控制的目的]:让发送方的发送速率不要太快,要让接收方来得及接收
然后来说一下很重要的例子,要注意理解,与后面的三次握手紧密度非常之大
- 首先在建立连接的时候B就告诉了A:“我的接收窗口rwnd = 400”。表示主机B的接受窗口最多可以接收400B的大小,然后设置了一个100字节长的报文段,即
DATA = 100
,数据报文段序号的初始值设置为1,即seq = 1
- 然后一开始主机A就向B发送了100B的大小,第一个字节序号为1
- 然后再发100B,第一个字节序号为为101
- 但是在接下来的数据接收中,
A主机继续向B主机发送了从[201]开始的数据
,但在途中丢失了。此时主机B发现主机A没有再发送数据过来了,因此向它发送过去一个确认报文段 - 【ACK】是一个确认字段,我们在TCP的首部格式中有说到过,
只有当ACK = 1 时ack才有效
- 【ack】是表示当前主机希望收到的下一个数据的首字节号,即
确认字段的值
- 【rwnd】表示接收窗口,接收方主机B将此窗口设置为300,表示它只能接收300大小的数据字节,而且是从201开始到500的这段范围,也就限定了主机A的发送窗口从
400->300
- 因为前200个字节的数据主机B已经完全接收了,所以主机A将其发送窗口向前滑动200字节⛸,将首字节号设置为201B,窗口大小设置为300B。
- 但是因为主机A没有接收到主机B从201~300字节的数据的回应,便开始启动这一块的
超时计时器
- 接下去主机A就向主机B分别发送了301B - 400B以及401B - 500B的数据,此时接收窗口就满了。
- 但此时主机A发现前面201~300B的
超时计时器
时间到了,但是主机B还是没有发来相关的响应,于是重新发送了一次从201开始的这100个数据报文段,这也就是我们在上面讲到过的【超时重传】
- 然后接下去主机B就发送了一条确认说“前面的500B我已经全部收到,现在我的接受窗口大小变为100,下一次希望收到501B为初始字节的数据”那此时主机A就可以确认主机B已经全部收到了500B之前的所有数据,于是便会将自己的发送窗口后移300个B,到501B的位置
- 接下去主机A又发送过来符合的100B数据,于是主机B的接受窗口就满了。此时主机B就发送回一个确认报文说“前面的600B我已经全部收到,现在把你的发送窗口变为0,不要再发送数据了”
从上面就可以看出主机B实现了三次流量控制,第一次将主机A的发送窗口大小从400->300
,第二次从300->100
,第三次就是从100->0
,通过【rwnd】这个接收窗口的控制,就使得主机A的发送窗口呈现出一个动态变化的趋势,也就是我们前面在讲到窗口值是在动态变化的
2、如何破解【死锁】局面❓
- 但是主机A要何时才能继续向主机B发送数据呢❓
也就是当主机B重新发出一个新的窗口值为止
。B主机会在它的接收缓存中腾出一些地方,把缓存当中的数据[主机A发送过来的600B]
上交给了应用层后,它的接收缓存中就又可以有一些存储空间了 - 于是这个时候主机B就又会向主机A发送一个
rwnd = 400
的报文段,告诉它你现在可以将自己的发送窗口设置为400,并且开始发送数据了。但是这个报文段呢若是在传输的过程中丢失了(〃>目<),主机A就收不到,此时主机B一直在等待主机A发送新的数据过来,主机A呢也等待主机B发送一个报文段过来告诉自己可以发数据了,于是它们就开始了一段漫长的等待.<{=.... - 以上这个局面叫做【死锁】,是双方在数据传输过程中很可能会出现的一个现象
那要怎么去解决这个局面呢?
- TCP为每一个连接都设有一个【
持续计时器
】,当连接的一方收到对方的零窗口通知后,就会启动这个计时器。也就是当前的主机A,接下去呢它会发送一个【探测报文段】,这个报文段中会有1B的数据,发送过去之后若是接收方给出的窗口值依旧是0,那么主机A就会重新设置持续计时器。 - 在这个时候呢主机B可能已经收到了应用层的通告,可以继续接收数据了;如果不是零,那么死锁的僵局就可以打破了。
- 从上述
流量控制
就可以看出TCP真的是非常的严谨,很好得控制了每一次数据的传输o((>ω< ))o
二、TCP的拥塞控制
1、拥塞控制的一般原理
首先来看看什么叫做【拥塞】
【拥塞】:在某段时间内,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏 👉∑对资源的需求 > 可用资源
① 解决网络拥塞的误区
很多人就认为解决网络拥塞的问题只需要增加一些资源即可
- 把节点缓存的存储空间扩大❌
- 把链路更换为更高速率的链路 ❌
- 把节点处理机的运算速度提高 ❌
- 其实对于上面的这几种做法,都是不可行的,网络拥塞并没有想象中的那么简单,可能你单纯地解决了某个表现的问题,但是会引发出一些其他层次的问题。
- 例如说
丢弃一些路由器分组
时,这一分组的源点就会重传这一分组,但是这又会间接导致更多的分组流入网络和被网络中的路由器丢弃
- 例如说
- 那其实我们可以看到,若只是采用一些简单的做法,在许多情况下,非但不能解决网络的拥塞问题,而且还可能使网络的性能更坏,所以我们要采取更加有效的方法
② 拥塞控制与流量控制的关系【重点理解✔】
在上一模块,我们讲到了流量控制,现在又说到了拥塞控制,那你可能会想它们之间会不会存在着什么关系呢?一起来看看🐎
- 对于【拥塞控制】而言, 其实就是要
防止过多的数据注入到网络
,使得网络中的路由器或链路不至于过载,而且它是一个全局性
的过程,会接收到不同主机、路由器所发送过来的数据,那么这个中心的交换节点就会同时被使用,从而到导致繁忙进而造成拥塞,可是呢接收方在这么繁忙的情况下又很难去知道、去查询是哪个主机出了问题 - 对于【流量控制】而言,要做的就是
抑制发送端发送数据的速率
,以使接收端来得及接收。它是一个点对点通信量的控制,是个端到端
的问题
可能在看了上面的叙述后依旧有点模糊,没关系,我通过一个生活中的小场景来叙述一下
- 其实对于它们二者可以看作为一个水龙头通过管道向水桶放水。对图a来说,它只有一个很小的桶,因为来不及接收从水管中注入的水,因此就告知水龙头那边的人【将水龙头拧得小一些,以此来减缓放水的速率】,这种两端之间的通信就叫做
流量控制
- 相反,对图b来说,它拥有一个很大的桶,完全可以接得下从水管中流过来的水,但是呢水管中间可能因为一些内部的各种污垢造成了拥塞,然后可以看到水管的上方已经积蓄了很多的水,因此就需要和管水龙头一方的人说【将水龙头拧得小一些,以此来减少流入水管内部的水量】,这种内部的缓解就相当于是
拥塞控制
👉对于同样的请求,都是将水龙头拧得小一些,但是目的却不一样。对照它们的原理之后,若是读者能明白,那也就懂了它们之间的区别
2、TCP的拥塞控制方法
了解了拥塞控制的一半原理,接下去我们来聊聊TCP面对这样的拥塞状况是如何应付的
为了集中讨论拥塞控制,假定:
- 数据是单方向传送的,对方只传送确认报文
- 接收方总是有足够大的缓存空间,因为
发送窗口的大小由网络的拥塞程度
来决定
① 接收窗口【rwnd】与拥塞窗口【cwnd】
- 在流量控制中,我们提到了
rwnd
接收窗口,是由接收方
维护的。表示接收方示意发送方自己可以接受的数据大小,以此来控制发送方发送数据的大小, - 在拥塞控制中我们再来聊聊一种窗口叫做
cwnd
拥塞窗口,它呢是由发送方
维护的。它的大小取决于网络的拥塞程度,并且是动态变化着的。因为上面我们假定接收方的接收窗口足够大,因为发送方只需要考虑拥塞窗口的大小即可
【发送方控制拥塞窗口的原则】:
- 只要网络没有出现拥塞,拥塞窗口就可以
增大一些
,将更多的数据发送出去,以此来提高网络利用率 - 当网络出现拥塞或可能要出现拥塞时,就把拥塞窗口
减小一点
,减少注入到网络的分组数,以便缓解网络出现的拥塞
发送方如何知道网络出现了堵塞?
- 没有按时收到对方的确认报文,超时重传计时器启动,便判断出网络出现了拥塞
来总结一下这两个窗口
👉【接受窗口 rwnd】:由接收方维护,会根据接收缓存设置的值,并告知给发送方,反映接收方容量
👉【拥塞窗口 cwnd】:由发送方维护,会根据自己估算的网络拥塞程度而设置的窗口值,反映网络当前容量
② 慢开始和拥塞避免算法
接下去我们来介绍一下拥塞控制中的算法,首先是
慢开始和拥塞避免算法
这两种,它们是配合使用的
📚 【慢开始算法原理】:由小到大逐渐将数据字节注入到网络中,即逐渐增加拥塞窗口的数值
- 接着你要知道一个东西叫做
最大报文段SMSS
,因为慢开始规定,每收到一个新的报文段后,可以把拥塞窗口增加最多一个SMSS的值。然后通过下面这个例子来介绍一下慢开始算法
- 从上图可以看出,对于发送方它首先设置【cwnd = 1】,发送出第一个报文段,然后接收方确认了这个报文段再发送回一个确认报文段,这一点我们在前面
TCP流量控制
中也有说到过,这么一趟来回就叫做一个轮次,也可以叫做往返时延RTT
- 经过了一个往返时延后,发送方便扩大拥塞窗口,令【cwnd = 2】,连续发出了两个报文段,然后接收方那个接收到之后就进行了返回确认,这是
第二轮的RTT
- 那发送方收到这两个确认报文段之后,便继续扩大自己的拥塞窗口,令【cwnd = 4】,一样,接收方接收到之后又会返回确认,这是
第三轮的RTT
- 依此类推。。。发送方若是
试探
到本网络的拥塞状况良好,就会不断地增加自己的拥塞窗口,尽快地将数据发送出去。这种慢开始的策略可以使得网络拥塞的概率减小↓
从上可以知道拥塞窗口在慢开始算法下会不断地增大,但是若是太大也不好,也会造成过多的数据涌入导致网络拥塞,因此便有了[慢开始门限ssthresh]
这么一个状态变量,它的用法如下👇
- 当【cwnd < ssthresh】时,使用上述的慢开始算法
- 当【cwnd > ssthresh】时,停止使用慢开始算法而改用
拥塞避免
算法 - 当【cwnd = ssthresh】时,即可使用
慢开始算法
,也可使用拥塞避免
算法
📚 【拥塞避免算法原理】:让拥塞窗口cwnd按线性规律缓慢增长,每个轮次RTT只加1
- 然后我们便可以通过下面这张曲线图来看出TCP的拥塞窗口cwnd是如何变化的
这一块可以听一听王道这个小姐姐讲的,还是蛮不错的👍
5.3.5 TCP拥塞控制
③ 快重传和快恢复算法
然后再来简单介绍一下
快重传和快恢复
这两个算法
📚 【快重传算法原理】:让发送方尽早知道发生了个别报文段丢失的情况,若发送发一连收到三个重复确认,便会立即重传接收方需要的报文段
- 对于这三次报文的重复确认,就是我们前面介绍过的
冗余ack
📚 【快恢复算法原理】:当发送端收到连续三个重复的确认时,不执行慢开始算法,而是执行快恢复算法算法
- 对于
慢开始算法
而言,会使拥塞窗口降到1后再使用拥塞避免算法慢慢升回到调整后的慢开始门限值 - 对于
快恢复算法
而言,不会使拥塞窗口降到最小值1,而是降到门限值ssthresh / 2
的位置,然后再次执行拥塞避免算法,使拥塞窗口缓慢地线性增大
以下是【TCP拥塞控制】的整个流程图,可以再对照回顾一下
三、总结与提炼
来总结一下本文所学习的内容
- 首先我们谈到了有关
TCP的流量控制
,在双方进行数据收发过程中,为了防止发送方发送的数据接收方无法接受或者是过载难以接受,于是便使用到了【滑动窗口】的机制去进行了一个收与发的限制,通过发送方和接收方不断地来回响应,以此让我们看出TCP协议的严谨性 - 接着我们又谈到了有关
TCP的阻塞控制
。首先清楚了它与流量控制之间的区别,以及它们之间的联系,为了方便大家理解,我用到了水桶接水的案例对它们做了区分。最后我们又细细地谈了谈有关TCP如何去实现一个阻塞控制,清楚了两个窗口,分别是【rwnd】接受窗口和【cwnd】拥塞窗口,也见识了TCP在进行阻塞控制时使用到的【慢开始和拥塞避免算法】、【 快重传和快恢复算法】,湖不过只是浅浅地提了一下,没有非常深入,有兴趣的小伙伴可以再去多了解一些里面的细节
2023年2月20日随记✍
相关文章:

计算机网络 | 谈谈TCP的流量控制与拥塞控制
文章目录一、TCP的流量控制1、利用滑动窗口实现流量控制【⭐⭐⭐】2、如何破解【死锁】局面❓二、TCP的拥塞控制1、拥塞控制的一般原理① 解决网络拥塞的误区② 拥塞控制与流量控制的关系【重点理解✔】2、TCP的拥塞控制方法① 接收窗口【rwnd】与拥塞窗口【cwnd】② 慢开始和拥…...
Flask入门(7):内置装饰器(钩子函数)
目录7.内置装饰器(钩子函数)7.1 before_request7.2 after_request7.3 before_first_request7.4 error_handlers7.5 template_filter7.6 template_global复习装饰器基础及其应用,可参考文章:闭包和装饰器 7.内置装饰器(…...
Java8新特性
✨作者:猫十二懿 ❤️🔥账号:CSDN 、掘金 、个人博客 、Github 🎉公众号:猫十二懿 写在最前面 在企业中更多的都是使用 Java8 ,随着 Java8 的普及度越来越高,很多人都提到面试中关于Java 8 也…...
哈希表题目:设计哈希集合
文章目录题目标题和出处难度题目描述要求示例数据范围解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析题目 标题和出处 标题:设计哈希集合 出处:705. 设计哈希集合 难度 3 级 题目描述 要求 不使用任何内建的哈希表库设计一个哈希…...

java static关键字 万字详解
目录 一、为什么需要static关键字: 二、static关键字概述 : 1.作用 : 2.使用 : 三、static修饰成员变量详解 : 1.特点 : 2.细节 : ①什么时候考虑使用static关键字? ②静态变量和非静态变量的区别? ③关于静态变量的初始化问题 : ④关于静态变…...

光谱实验反射、透射光谱测量
标题反射、透射光谱测量的基本原理 暗背景/基线:Dark………………………………………………………………0% (空)白参考:Reference…………………………………………………………100% 样品反射/透射光谱:Sampl…...

【基础算法】之 冒泡排序优化
冒泡排序思想基本思想: 冒泡排序,类似于水中冒泡,较大的数沉下去,较小的数慢慢冒起来(假设从小到大),即为较大的数慢慢往后排,较小的数慢慢往前排。直观表达,每一趟遍历,…...
Python | 线程锁 | 3分钟掌握【同步锁】(Threading.Lock)
文章目录概念无锁加锁死锁解决死锁概念 threading.Lock 同步锁,可以用于保证多个线程对共享数据的独占访问。 当一个线程获取了锁之后,其他线程在此期间将不能再次获取该锁,直到该线程释放锁。这样就可以保证共享数据的独占访问,…...

Linux下安装MySQL8.0的详细步骤(解压tar.xz安装包方式安装)
Linux下安装MySQL8.0的详细步骤 第一步:下载安装配置 第二步:修改密码,并设置远程连接(为了可以在别的机器下面连接该mysql) 第三步:使用Navicat客户端连接 搞了一台云服务器,首先要干的活就是…...

leaflet 绘制多个点的envelope矩形(082)
第082个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中如何根据多边形的几个坐标点来绘制envelope矩形。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共78行)安装插件相关API参考:专栏目标示例…...

CAJ论文怎么批量免费转换成Word
大家都知道CAJ文件吗?这是中国学术期刊数据库中的文件,这种文件类型比较特殊。如果想要提取其中的内容使用,该如何操作呢?大家可以试试下面这种免费的caj转word的方法,多个文档也可以一起批量转换。准备材料:CAJ文档、…...
面试必问: 结构体大小的计算方法
结构体大小的计算需同时满足以下几点 一、结构体成员的偏移量必须是当前成员大小的整数倍。(0是任何数的整数倍) 举一个例子 struct Test1{char a; // 当前偏移量为0,是char所占字节数1的整数倍 所以所占大小为1char b; …...
Java中super函数的用法
1 问题 Java中super函数有很多方法,在使用的时候我们应该如何正确区分? 2 方法 三种用法: 访问父类的方法。 调用父类构造方法。 访问父类中的隐藏成员变量。 class A{ int x,y; A(int x,int y){ System.out.println("A"); } } cla…...

第十一届“泰迪杯”数据挖掘挑战赛携“十万”大奖火热来袭
第十一届“泰迪杯”数据挖掘挑战赛 竞赛组织 主办单位: 泰迪杯数据挖掘挑战赛组织委员会 承办单位: 广东泰迪智能科技股份有限公司 人民邮电出版社 协办单位: 重庆市工业与应用数学学会、广东省工业与应用数学学会、广西数学学会、河北省工业…...

分享三个可以在家做的正规兼职工作,看到就是赚到
你可以在家做正式的兼职工作。在线兼职工作值得考虑,时间相对自由。在线兼职收入可能不如线下滴滴和外卖立竿见影,但仍然可以坚持收入。有些人比工作工资发展得更高。当然,天上不会有馅饼,不劳无获。那么有哪些正规的兼职可以在家…...

javaFx实现鼠标穿透画布,同时操作画布和桌面,背景透明,类似ppt批注
一、功能需要由来和大致效果 今天,我们要用javaFx来实现一个鼠标穿透画布的功能,该需求来自于在我们的javaFx桌面应用中,需要实现一个悬浮的桌面侧边工具栏,在工具栏中有画笔绘制,批注的功能,能够实现在任何…...

客户服务知识库的最佳实践7个步骤
每个公司的声誉都依赖于客户,如果客户因为想要购买你的产品找到你,但是了解到你的客户服务做的不好,可能也会放弃你的产品,就像市场营销依赖于潜在客户的关系一样,公司的服务部门也需要依赖于现有客户的关系࿰…...

多重继承的虚函数表
同一个类,不同对象使用同一张虚函数表 不同类使用不同的虚函数表 子类自己添加的虚函数(非重写),在VS中是将此放在第一个继承类的虚函数表里. #include <iostream> using namespace std;class Father { public:virtual void func1() { cout << "Father::f…...
第11篇:Java开发工具使用和代码规范配置
目录 1、IntelliJ IDEA 简介 2. IntelliJ IDEA 下载 3. IntelliJ IDEA 安装和使用 3.1 安装到Windows下 3.2 快速编写 Hello World 程序...
Rust模式匹配
模式匹配 模式匹配是从函数式编程语言(例如:Haskell,Lisp)吸收而来的,用于为复杂的类型系统提供一个轻松的解构能力。rust使用match来提供模式匹配的功能。mathc类似于其它编程语言中的switch-case,但是远…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...