[Linux][网络][TCP][四][流量控制][拥塞控制]详细讲解

目录

  • 1.流量控制
  • 2.拥塞控制
    • 0.为什么要有拥塞控制,不是有流量控制么?
    • 1.什么是拥塞窗口?和发送窗口有什么关系呢?
    • 2.怎么知道当前网络是否出现了拥塞呢?
    • 3.拥塞控制有哪些算法?
    • 4.慢启动
    • 5.拥塞避免
    • 6.拥塞发生
    • 7.快速恢复


1.流量控制

  • 发送方不能无脑的发数据给接收方,要考虑接收方处理能力

  • 如果一直无脑地发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费

  • 为了解决这种现象发生,TCP提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制

  • 假设以下场景:客户端是接收方,服务端是发送方假设接收窗口和发送窗口相同,都为200,假设两个设备在整个传输过程中都保持相同的窗口大小,不受外界影响

  • 根据下图的流量控制,说明下每个过程:

    • 客户端向服务端发送请求数据报文
      • **说明:**本次例子是把服务端作为发送方,所以没有画出服务端的接收窗口
    • 服务端收到请求报文后,发送确认报⽂和80字节的数据,于是可用窗口Usable减少为120字节,同时SND.NXT指针也向右偏移80字节后,指向321,这意味着下次发送数据的时候,序列号是321
    • 客户端收到80字节数据后,于是接收窗口往右移动80字节, RCV.NXT也就指向321,这意味着客户端期望的下⼀个报文的序列号是 321,接着发送确认报⽂给服务端
    • 服务端再次发送了120字节数据,于是可用窗口耗尽为0,服务端无法再继续发送数据
    • 客户端收到120字节的数据后,于是接收窗口往右移动120字节, RCV.NXT也就指向441,接着发送确认报文给服务端
    • 服务端收到对80字节数据的确认报文后, SND.UNA指针往右偏移后指向321,于是可用窗口Usable增大到80
    • 服务端收到对120字节数据的确认报文后, SND.UNA指针往右偏移后指向441,于是可用窗口Usable增大到200
    • 服务端可以继续发送了,于是发送了160字节的数据后, SND.NXT指向601,于是可用窗口Usable减少到40
    • 客户端收到160字节后,接收窗口往右移动了160字节, RCV.NXT也就是指向了601,接着发送确认报文给服务端
    • 服务端收到对160字节数据的确认报文后,发送窗口往右移动了160字节,于是SND.UNA指针偏移了160后指向601,可用窗口Usable也就增大至了200

请添加图片描述

  • 接收端将自己可以接收的缓冲区大小放入TCP首部中的"窗口大小"字段,通过ACK端通知发送端
  • 窗口大小字段越大, 说明网络的吞吐量越高
  • 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端
  • 发送端接受到这个窗口之后,就会减慢自己的发送速度
  • 如果接收端缓冲区满了, 就会将窗口置为0,这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端

2.拥塞控制

0.为什么要有拥塞控制,不是有流量控制么?

  • 前面的流量控制是避免「发送方」的数据填满「接收方」的缓存,但是并不知道网络的中发生了什么
  • ⼀般来说,计算机网络都处在⼀个共享的环境,因此也有可能会因为其他主机之间的通信使得网络拥堵
  • 在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时TCP就会重传数据,但是⼀重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大
  • 所以,TCP不能忽略网络上发生的事,它被设计成⼀个无私的协议,当网络发送拥塞时,TCP会自我牺牲,降低发送的数据量
  • 于是,就有了拥塞控制,控制的目的就是避免「发送方」的数据填满整个网络
  • 为了在「发送方」调节所要发送数据的量,定义了⼀个叫做「拥塞窗口」的概念

1.什么是拥塞窗口?和发送窗口有什么关系呢?

  • 拥塞窗口cwnd是发送方维护的⼀个的状态变化,它会根据网络的拥塞程度动态变化的
  • 前面提到过发送窗口swnd和接收窗口rwnd是约等于的关系,那么由于加入了拥塞窗口的概念后,此时发送窗口的值是**swnd = min(cwnd, rwnd)**,也就是发送窗口和接收窗口中的最小值
  • 拥塞窗口cwnd变化的规则
    • 只要网络中没有出现拥塞,cwnd就会增大
    • 但网络中出现了拥塞,cwnd就减少

2.怎么知道当前网络是否出现了拥塞呢?

  • 只要「发送方」没有在规定时间内接收到ACK应答报文,也就是发生了超时重传,就会认为网络出现了拥塞

3.拥塞控制有哪些算法?

  • 慢启动
  • 拥塞避免
  • 拥塞发生
  • 快速恢复

4.慢启动

  • TCP在刚建立连接完成后,首先是有个慢启动的过程,这个慢启动的意思就是⼀点⼀点的提高发送数据包的数量, 如果一上来就发大量的数据,这不就是给网络添堵吗?
  • 慢启动的算法记住⼀个规则就行:当发送⽅每收到⼀个ACK,拥塞窗口cwnd的大小就会加1
  • 这里假定拥塞窗口cwnd和发送窗口swnd相等,下面举个例子:
    • 连接建立完成后,⼀开始初始化cwnd = 1,表示可以传⼀个MSS大小的数据
    • 当收到⼀个ACK确认应答后,cwnd增加1,于是⼀次能够发送2个
    • 当收到2个的ACK确认应答后, cwnd增加2,于是就可以比之前多发2个,所以这⼀次能够发送4个
    • 当这4个的ACK确认到来的时候,每个确认cwnd增加1,4个确认cwnd增加4,于是就可以比之前多发4个,所以这⼀次能够发送8个
    • 可以看出慢启动算法,发包的个数是指数性的增长

请添加图片描述

  • 那慢启动涨到什么时候是个头呢?
  • 有⼀个叫慢启动门限ssthresh(slow start threshold)状态变量
    • cwnd < ssthresh时,使⽤「慢启动算法」
    • cwnd >= ssthresh时,就会使⽤「拥塞避免算法」

5.拥塞避免

  • 前⾯说到,当拥塞窗口cwnd「超过」慢启动门限ssthresh就会进入拥塞避免算法
  • ⼀般来说ssthresh的大小是65535字节
  • 进入拥塞避免算法后,它的规则是:每当收到⼀个 ACK 时,cwnd增加1/cwnd
  • 接上前面的慢启动的例子,现假定ssthresh为8:
    • 当8个ACK应答确认到来时,每个确认增加1/8,8个ACK确认cwnd⼀共增加1,于是下次能够发送9个MSS大小的数据,变成了线性增长
    • 可以发现,拥塞避免算法就是将原本慢启动算法的指数增长变成了线性增长,还是增长阶段,但是增长速度缓慢了⼀些
    • 就这么⼀直增长着后,网络就会慢慢进⼊了拥塞的状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。当触发了重传机制,也就进入了「拥塞发生算法」
      请添加图片描述

6.拥塞发生

  • 当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:

    • 超时重传
    • 快速重传
  • 发生超时重传的拥塞发生算法

    • ssthresh和cwnd的值会发生变化:
      • ssthresh设为cwnd/2
      • cwnd重置为1
    • 接着,就重新开始慢启动,慢启动是会突然减少数据流的
      • ⼀旦「超时重传」,马上回到解放前。但是这种方式太激进了,反应也很强烈,会造成网络卡顿
        请添加图片描述
  • 发生快速重传的拥塞发生算法

    • 还有更好的方式,前⾯讲过「快速重传算法」。当接收⽅发现丢了⼀个中间包的时候,发送三次前⼀个包的ACK,于是发送端就会快速地重传,不必等待超时再重传
    • TCP认为这种情况不严重,因为大部分没丢,只丢了⼀小部分,则ssthresh和cwnd变化如下:
      • cwnd = cwnd/2 ,也就是设置为原来的⼀半
      • ssthresh = cwnd
      • 进⼊快速恢复算法

7.快速恢复

  • 快速重传和快速恢复算法⼀般同时使用,快速恢复算法是认为,你还能收到3个重复ACK说明网络也不那么糟糕,所以没有必要像RTO超时那么强烈
  • 正如前⾯所说,进⼊快速恢复之前, cwnd和ssthresh已被更新了
    • cwnd = cwnd/2 ,也就是设置为原来的⼀半
    • ssthresh = cwnd
  • 然后,进入快速恢复算法如下
    • 拥塞窗口**cwnd = ssthresh + 3**(3的意思是确认有3个数据包被收到了)
    • 重传丢失的数据包
    • 如果再收到重复的ACK,那么cwnd增加1
    • 如果收到新数据的ACK后,把cwnd设置为第⼀步中的ssthresh的值,原因是该ACK确认了新的数据,说明从duplicated ACK时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进⼊拥塞避免状态

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

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

相关文章

LabelImg下载及目标检测数据标注

为什么这一部分内容这么少会单独拎出来呢&#xff0c;因为后期会接着介绍YOLOv8中的其他任务&#xff0c;会使用其他软件进行标注&#xff0c;所以就单独区分开来每一个任务的标注方式了。 这一部分就介绍目标检测任务的标注&#xff0c;数据集是我从COCO2017Val中抽出来两类&a…

矩阵相关运算1

矩阵运算是线性代数中的一个核心部分&#xff0c;它包含了许多不同类型的操作&#xff0c;可以应用于各种科学和工程问题中。 矩阵加法和减法 矩阵加法和减法需要两个矩阵具有相同的维度。操作是逐元素进行的&#xff1a; CAB or CA−B其中 A,B 和 C 是矩阵&#xff0c;且 C…

RTT PIN设备学习

获取GPIO编号 GET_PIN(port, pin)#define LED_BLUE_PIN GET_PIN(A, 0)设置引脚模式 void rt_pin_mode(rt_base_t pin, rt_base_t mode);设置引脚电平 void rt_pin_write(rt_base_t pin, rt_base_t value);rt_base_t pin 同上&#xff0c; 为引脚编号&#xff0c;尽量通过宏定…

新建的springBoot WEB项目无法自动返回html模版(gradle+kotlin版本)

最近研究了springBoot创建web项目&#xff0c; 第一步服务端返回字符串没有问题&#xff0c;第二步返回html时&#xff0c;还是返回的字符串。 文章目录 一、参考方案二、新建springBoot web项目三、启动项目的三种方式 一、参考方案 将控制器类的 RestController 改为 Contro…

代码随想录算法训练营第六十天| 647. 回文子串,516.最长回文子序列,动态规划总结篇

题目与题解 参考资料&#xff1a;动态规划总结篇 647. 回文子串 题目链接&#xff1a;647. 回文子串 代码随想录题解&#xff1a;647. 回文子串 视频讲解&#xff1a;动态规划&#xff0c;字符串性质决定了DP数组的定义 | LeetCode&#xff1a;647.回文子串_哔哩哔哩_bilibili …

【再探】设计模式—适配器、装饰及外观模式

结构型设计模式是用于设计对象和类之间关系的一组设计模式。一共有7种&#xff1a;适配器模式、装饰器模式、外观模式、桥接模式、组合模式、享元模式及代理模式。 1 适配器模式 需求&#xff1a;在软件维护阶段&#xff0c;已存在的方法与目标接口不匹配&#xff0c;需要个中…

每日一题5:Pandas-修改列

一、每日一题 一家公司决定增加员工的薪水。 编写一个解决方案&#xff0c;将每个员工的薪水乘以2来 修改 salary 列。 返回结果格式如下示例所示。 解答&#xff1a; import pandas as pddef modifySalaryColumn(employees: pd.DataFrame) -> pd.DataFrame:employees.loc[…

最后一块石头的重量 II ,目标和,一和0

最后一块石头的重量 II&#xff08;0-1背包问题 将石头尽可能分为两堆重量一样的&#xff0c;进行相撞则为0 class Solution {public int lastStoneWeightII(int[] stones) {int sum0;for(int x:stones){sumx;}int targetsum/2;int[] dpnew int[target1];//dp[j]表示最大石堆的…

【一起深度学习-----VGG】

VGG 原理图&#xff1a; 原理图&#xff1a; 为啥要使用VGG块呢&#xff1f; 对于AlexNet网络来说&#xff0c;虽然十分高效了&#xff0c;但是它并没有提供一个通用的模板&#xff0c;方便后续的研究。 故采用了模块化的思想&#xff0c;方便重复使用。 其实对比于AlexNet神经…

必应bing国内广告怎么做付费推广,提升产品曝光?

必应Bing作为微软旗下重要的搜索引擎平台&#xff0c;拥有着不可忽视的用户基础和市场潜力。对于寻求拓宽市场、提高品牌知名度的企业而言&#xff0c;利用必应Bing进行付费推广无疑是明智之选。通过必应Bing国内广告进行高效付费推广&#xff0c;助您轻松提升产品曝光度。 一…

C++:多态-虚函数

C 中的多态性是面向对象编程中的一个重要概念&#xff0c;它允许在运行时选择不同的函数实现&#xff0c;以适应不同类型的对象。 多态的种类 编译时多态性&#xff08;Compile-time Polymorphism&#xff09;&#xff1a;也称为静态多态性或早期绑定&#xff0c;指在编译时确…

【Git】Git学习-13:Gitee和GitLab的使用

学习视频链接&#xff1a;【GeekHour】一小时Git教程_哔哩哔哩_bilibili​编辑https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 流程 1. 创建仓库/已有仓库 2. 克隆到本地/在远程仓库关联 git clone 仓库地址 git remote add 仓库别…

[Kotlin]创建一个私有包并使用

1.创建Kotlin项目 创建项目&#xff1a; 在Android Studio或其他IDE中选择“Create New Project”。选择Kotlin和Gradle作为项目类型和构建系统。指定项目名称和位置&#xff0c;完成设置。 添加依赖: 如果你的库需要额外的依赖&#xff0c;可以在 build.gradle (Module: app…

Axure中继器介绍以及案例分享

中继器是 Axure 中一个比较高阶的应用&#xff0c;它可以让我们在纯静态网页中模拟出类似带有后台数据交互的增删改查的效果。 一、中继器的基本使用方法&#xff1a; 整体流程分为三个步骤 ☆创建中继器 我们先在 Axured画布中拖入一个中继器元件 双击中继器后的效果 打开之…

APP 在华为应用市场上架 保姆级别详细流程

1、作为一名干开发的程序员&#xff0c;第一次能把自己的APP 上架&#xff0c;对自己来说是多么有意义的一项成就 2、创建一个 华为的开发者账号 根据提示填写完注册的信息https://developer.huawei.com/consumer/cn/product/华为开发者产品 | 开发者平台 | 流量变现 | 华为开…

商家制作微信小程序有什么好处?微信小程序的制作有哪些步骤和流程

微信小程序全面指南 微信小程序是微信生态系统中一项革命性的功能&#xff0c;为希望与庞大的微信用户群体互动的企业提供了独特的融合便捷性和功能性的体验。本全面指南深入探讨了微信小程序的世界&#xff0c;强调了其重要性、工作原理以及实际用例&#xff0c;特别是针对企…

CCE云原生混部场景下的测试案例

背景 企业的 IT 环境通常运行两大类进程&#xff0c;一类是在线服务&#xff0c;一类是离线作业。 在线任务&#xff1a;运行时间长&#xff0c;服务流量及资源利用率有潮汐特征&#xff0c;时延敏感&#xff0c;对服务SLA 要求高&#xff0c;如电商交易服务等。 离线任务&…

DOTA-Gly-Asp-Tyr-Met-Gly-Trp-Met-Asp-Phe-NH2,1306310-00-8,是一种重要的多肽化合物

一、试剂信息 名称&#xff1a;DOTA-Gly-Asp-Tyr-Met-Gly-Trp-Met-Asp-Phe-NH2CAS号&#xff1a;1306310-00-8结构式&#xff1a; 二、试剂内容 DOTA-Gly-Asp-Tyr-Met-Gly-Trp-Met-Asp-Phe-NH2是一种重要的多肽化合物&#xff0c;其CAS号为1306310-00-8。该多肽包含一个DO…

Spring_概述

Spring 官网Spring Framework&#xff08;Spring&#xff09;文档位置重点内容Overview 官网 Spring官网 Spring Framework&#xff08;Spring&#xff09; 文档位置 重点 IoC容器AOP&#xff1a;面向切面编程AOT&#xff1a;ahead of time&#xff0c;提前编译Web 框架&…

C++中的异常处理方式

目录 一、异常 二、C语言中对错误的处理 三、C中的异常处理 四、异常的抛出和捕获 五、异常的重新抛出 六、C标准库中的异常体系 七、异常的规范 一、异常 在C中&#xff0c;异常是程序运行期间发生的意外或错误情况。这些情况可能会导致程序无法继续正常执行&#xff0c;…