【TCP】核心机制:滑动窗口、流量控制和拥塞控制

news2024/9/23 15:31:32

文章目录

  • 滑动窗口
    • 窗口
    • 滑动
    • 滑动窗口丢包
  • 流量控制
  • 拥塞控制
    • 窗口大小变化过程

滑动窗口

有一类算法题,就是通过滑动窗口的思想来解决的,算法中的“滑动窗口”借鉴自 TCP 的滑动窗口

TCP 是要保证可靠传输的==>代价,降低了传输的效率(重传,确认重传等操作)

TCP 希望能在可靠传输的基础上,也有一个不错的效率,就引入了“滑动窗口

  • 这里的提高效率,只是“亡羊补牢”,使传输效率的损失,尽可能降低
  • 引入滑动窗口,也不能使传输效率比 UDP 还高

窗口

image.png|495
A 每次都需要收到 ACK 之后,再发下一个数据

  • 低效,有大量的时间都消耗在等待 ACK 上

改进方案:
image.png|400

  • 把“发送一个等待一个”改为“发送一批等待一批”
  • 把多次等待 ACK 的时间合并时一份了
  • 批量发送的数据越多,效率就越高
  • 批量发送的数据中,不需要等待的数据的量,称为“窗口大小
    • 批量发送的是数据的字节数,而不是条
    • 窗口就是一次能发多少数据,具体的数据量就是窗口大小

滑动

image.png|484

当收到了第一个 ACK 之后,不会继续等待剩下的 3 个 ACK 到了之后再发下一组,而是收到这个 ACK 之后,就立即发送下一条数据

  • 收到 2001 ACK,说明 1001-2000 数据得到应答了
  • 然后立即发送 5001-6000 这个数据,此时等待的 ACK 范围就是 2001-6000(四份数据),窗口大小还是 4000
  • 窗口大小不变,只是窗口所处的位置改变了

每收到一个 ACK,窗口就往后挪,因为 ACK 是接连不断的发送的,所以窗口就往后挪动了,就滑起来了

滑动窗口就是批量传输数据的一种实现方式

滑动窗口丢包

image.png
情况一:
不需要任何处理;批量发数据,批量 ACK,多个 ACK 只是丢其中的一部分,不可能全丢
确认序号的含义:表示的是收到的数据最后一个字节的下一个序号。进一步理解成,确认序号之前的数据,都已经收到了,接下来你要发的数据就从确认序号这里往后发

  • 虽然 1001 ACK 丢了,但是 2001 ACK 到达了。发送方收到 2001 ACK 之后,意味着 2001 之前的数据都已经收到了
  • 后一个 ACK 能涵盖前一个 ACK 的意义

情况二:
1001-2000 丢包之后:

  • A 发过去 2001-3000 之后,此时,B 收到的数据为:1-10002001-3000
  • 此时 B 收到 2001-3000 的时候,返回的 ACK 确认序号不是 3001,而是 1001
  • B 就是在向 A 索要 1001 的数据
  • 接下来,B 和搜到的 3001-40004001-50005001-6000.… 对应的 ACK 确认序号都是 1001
  • 主机 A 连续收到 1001 这样的 ACK 之后,主机 A 意识到 1001 数据包丢了,于是主机重传 1001-2000
  • 1001-2000 重传过来之后,由于执勤啊 2001-7000 数据都是已经发过了,此时的 1001-2000 相当于是补全了之前的空缺,此时就意味着 1-7000 的数据都齐了,于是接下来索要 7001 开头的数据即可

上述过程,没有任何拖泥带水的操作,快速的识别出了是哪个数据丢包,并且针对性的进行了重传,其他顺利到达的数据都无需重传,这个过程称为“快速重传
快速重传可以视为是“滑动窗口”下搭配的“超时重传”

滑动窗口/快速重传、确认应答/超时重传
他们彼此之间并不冲突。如果通信双方单位时间发送的数据量比较少,就是按照之前的确认应答/超时重传;如果单位时间内发送的数据比较多,就会按照滑动窗口/快速重传

流量控制

滑动窗口,窗口大小对于传输数据的性能是直接相关的,但窗口能无限大吗?
通信是双方的事,发送方发的快乐,你也得确保接收方能处理得过来

image.png

  • 接收缓冲区:内核中的内存空间,每个 Socket 对象都有一个这样的缓冲区,其类似于一个阻塞队列(BlockingQueue
  • 这个传输过程就是一个“生产者消费者模型”
    • 如果发送速度特别快,消费数据比较慢,就会使接收缓冲区满,此时如果继续强行发送数据,就会“丢包”(被接收方丢弃)
    • 这里就需要根据接收方的处理能力,反向制约发送方的发送速度,这就是流量控制

此处可以通过“定量”的方式来实现制约,看接收缓冲区剩余空间大小
|476

  • 如果空闲空间比较大,就可以认为应用程序处理速度比较快
    • 就可以让发送方发的快一点,设置一个更大的窗口大小
  • 如果空闲空间比较小,就可以认为应用程序处理速度比较慢
    • 就可以让发送方发的慢一点,设置一个更小的窗口大小

TCP 中,接收方收到数据的时候,就是把接收缓冲区剩余空间大小通过 ACK 数据报,反馈给发送方。之后发送方就可以依据这个数据来设置发送的窗口大小了image.png|413

  • 这里面的“16 位窗口大小”体现了刚才谈到的接收方接收缓冲区的剩余空间,这个属性只有在 ACK 报文中才有效(ACK 这一位为 1

此处的 16 位表示范围 64KB,是否意味着发送方窗口大小最大就是 64KB 呢?

  • 不是的
  • 选项中,可以设置一个特殊的选项“窗口扩展因子
  • 发送方的窗口大小 = 窗口大小 << 窗口扩展因子(左移运算符)
    • 左移一位就相当于 *2

image.png

此时假设接收方应用程序没有读取任何数据,就是一直在生产,却没有消费,最后发送方的窗口大小就变成 0 了,接收缓冲区就满了,发送方就不能再发送了。那发送方不发送数据,要等待多久呢?

  • 原本是要通过 ACK 来知道对方接收缓冲区中的剩余空间的,但是不发送数据就没有 ACK 呀
  • 所以当窗口大小为 0 的时候,等待一个“超时时间”后,会发送一个“窗口探测包”,不携带任何业务数据(载荷部分是空的),只是为了触发 ACK,通过这个操作来查询一下,接收方接收缓冲区剩余多少。如果还是 0,就过一会之后再查
  • 接收方也会在接收缓冲区不为 0 的时候(消费了一定数据之后),主动触发一个“窗口更新通知”这样的数据,告诉接收方缓冲区内的余量情况

流量控制,也不是 TCP 独有的机制,其他的协议也可能会涉及到流量控制(比如,数据链路层中有的协议也支持流量控制)

拥塞控制

这个操作,也是和刚才的流量控制有关联的

  • 滑动窗口==>踩油门
  • 流量控制==>踩刹车
  • 拥塞控制==>踩刹车

流量控制,是站在接收方的视角来限制发送方的速度
拥塞控制,是站在传输链路的视角来限制发送方的速度

image.png|582

假设 B 处理速度非常快,此时 A 可以无限速度的发送数据吗?

  • 当然不行,中间的链路可能顶不住
    • 此时节点 a 已经负载很高了,如果 A 发送很快,那么这个节点可能就直接丢包了
      流量控制,就可以精准的使用接收方接收缓冲区来进行衡量
      考量中间节点的情况就麻烦了
  1. 中间的节点非常多
  2. 每次传输数据,走的路线还都不一样
  3. 中间哪个节点遇到瓶颈了不清除
  4. 中间节点传输数据不止有 A 的,还有很多其他设备的数据

别害怕,可以通过做实验的方式,来找到一个合适的发送速度

  • 在拥塞控制中,将中间所有的节点视为一个整体,不关心内部的细节
    然后进行“实验”(面多加水,水多加面)
  1. 先按照一个比较小的速度,发送数据
  2. 数据非常畅通,没有丢包,说明网络上传输数据整体是比较畅通的,就可以加快传输数据的速度
  3. 增大到一定的速度之后,发现出现丢包了,说明网络上可能存在拥堵了,就减慢传输数据的速度
  4. 减速之后,发现又不丢包了,继续再加速
  5. 加速之后又丢包了,再减速

  6. 一直持续地动态变化,这是很科学的,因为网络环境也是一直变化的,所以以变化应对变化

流量控制会限制发送窗口,拥塞控制也会限制发送窗口。这两个机制会同时起作用,最终实际的发送窗口大小,取决于上述两个机制得到的发送窗口较小值

窗口大小变化过程

image.png|534

  1. 刚开始传输数据,拥塞窗口会非常小,用一个很小的速度来发送数据(慢启动

    • 因为当前网络是否拥堵是未知的
  2. 不丢包,增大窗口大小(指数增长

    • 每过一轮,窗口大小就翻倍,增长速度特别快,会在短时间内达到很大的窗口大小
  3. 增长到一定程度,达到某个指定的阈值,此时即使没有丢包,也会停止指数增长,变成线性增长

    • 这样就不会太快的进入丢包的节奏
  4. 线性增长也会持续使发送速度越来越快,达到某个情况下,就会出现丢包

    • 一旦出现丢包,接下来就需要减慢发送速度,也就是减少窗口大小

此时有两种处理方式:

  1. 经典的方案,回归慢启动开始非常小的初始值,先指数增长,再线性增长
  2. 现在的方案,回归到新的阈值上,直接进行线性增长(以后都不会指数增长了)

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

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

相关文章

【机器学习】3. 欧式距离,曼哈顿距离,Minkowski距离,加权欧式距离

Euclidean - L2 norm L2范数 D ( A , B ) ( a 1 − b 1 ) 2 ( a 2 − b 2 ) 2 . . . D(A,B) \sqrt{(a_1-b_1)^2(a_2-b_2)^2 ...} D(A,B)(a1​−b1​)2(a2​−b2​)2... ​ Manhattan D ( A , B ) ∣ a 1 − b 1 ∣ ∣ a 2 − b 2 ∣ . . . D(A,B) \sqrt{|a_1-b_1||a_…

全网最简单的Java设计模式【九】策略模式-实战中最常用的设计模式之一

策略模式是一种行为设计模式&#xff0c;它允许你定义一系列的算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可以相互替换。该模式让算法的变化独立于使用算法的客户。在实际开发中&#xff0c;策略模式可以帮助我们减少大量的 if-else 或 switch 条件判断语句&…

产品的需求分析

一、需求 1.需求概念 用户的预期与现实存在在差异 用户所期望的明确的解决方案 2.需求的常用形式 提问题 提目的 提方案 3.需求的来源 外部需求&#xff1a;用户、市场、其他竞品 内部需求&#xff1a;业务部门、产品经理 4.需求测试方法 定性方式&#xff1a;逻辑…

【生日视频制作】江边夜景游轮观光船霓虹灯AE模板修改文字软件生成器教程特效素材【AE模板】

游轮观光船生日视频制作教程AE模板修改文字特效软件生成器素材 怎么如何做的【生日视频制作】江边夜景游轮观光船霓虹灯AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频

鸿蒙(API 12 Beta3版)【使用Image完成图片接收器】图片开发指导依赖JS对象

图像接收类&#xff0c;用于获取组件surface id&#xff0c;接收最新的图片和读取下一张图片&#xff0c;以及释放ImageReceiver实例。 开发步骤 添加依赖 在进行应用开发之前&#xff0c;开发者需要打开native工程的src/main/cpp/CMakeLists.txt&#xff0c;在target_link_…

【Qt】Qt系统 | Qt事件| 鼠标事件

文章目录 鼠标事件鼠标点击事件鼠标释放事件鼠标双击事件鼠标移动事件 滚轮事件 在 Qt 中&#xff0c;鼠标事件是用 QMouseEvent 实现的。当在窗口中按下鼠标或者移动鼠标时&#xff0c;都会产生鼠标事件 鼠标事件 鼠标点击事件 鼠标按下时通过 虚函数 mousePressEvent() 来…

系统编程—进程

一、进程的概念 1.程序与进程的区别 程序:编译后产生的&#xff0c;格式为ELF的&#xff0c;存储于硬盘的文件。可以通过 readelf -s [文件名] 查看文件信息 …

使用OpenRewrite升级SpringBoot项目

使用OpenRewrite升级SpringBoot项目 什么是OpenRewrite? OpenRewrite是一个强大的开源自动化源代码重构工具,专为大规模代码库设计。它的核心理念是通过程序化的方式来改变源代码,而不是依赖于手动编辑或简单的查找替换。 OpenRewrite的主要特点和优势包括: 自动重构: Open…

Unity动画模块 之 Animator中一些常见参数

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正 我发现我忘了写Animator了&#xff0c;正好有些不常用的参数还没怎么认识,笔记来源于唐老狮 1.状态窗口参数 2.连线参数…

Lesson05--C/C++内存管理

1. C/C内存分布 2. C语言中动态内存管理方式 3. C中动态内存管理 4. operator new与operator delete函数 5. new和delete的实现原理 6. 定位new表达式(placement-new) 7. 常见面试题 1. C/C内存分布 为了方便管理内存被分为了以上的区域 我们来看下面的一段代码和相关问题 …

数据结构(邓俊辉)学习笔记】优先级队列 08——左式堆:结构

文章目录 1. 第一印象2. 堆之合并3. 奇中求正4. NPL5. 左倾性6. 左展右敛 1. 第一印象 在学习过常规的完全二叉堆之后&#xff0c;我们再来学习优先级队列的另一变种&#xff0c;也就是左式堆。所谓的左式堆&#xff0c;也就是在拓扑形态上更加倾向于向左侧倾斜的一种堆&#…

Vue3 项目结构

1.main.ts 2.简单写一个src下的结构 App.vue 根组件 <template><div class"app"><!-- html --><h1>你好啊!</h1></div> </template><script lang"ts"> //js 或 tsexport default {name:App,//组件名 }…

MySQL数据库锁机制(全面讲解)

目录 1、全局锁 1.1、全局锁使用语法 1.2、备份数据库&#xff08;不使用全局锁&#xff09; 2、表锁 2.1、读写锁 读锁 写锁 2.2、元数据锁&#xff08;meta data lock MDL&#xff09; 2.3、意向锁 3、行锁 3.1、共享锁和排他锁 共享锁&#xff08;S锁&#xff…

原来marker还能这么玩

在Web GIS开发中&#xff0c;Marker&#xff08;标记&#xff09;是一个基本但强大的工具。今天&#xff0c;我们将探讨如何通过不同的API调用&#xff0c;将Marker玩出新花样&#xff0c;让地图更加生动有趣。 最基础的Marker用法是在地图上标记一个具体位置。我们可以通过“m…

【Unity3D小技巧】Unity3D中实现对InputField的自定义输入限制实例

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群&#xff1a;398291828 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 InputField是UGUI的文本输入框&#xff0c;自带的…

粘包,Telnet,SSH,Wireshark

一&#xff0c;粘包 原因&#xff1a;tcp为流式套接字&#xff0c;数据与数据间没有边界&#xff0c;导致多次数据粘到一起。 解决&#xff1a; 1.规定一些数据间的间隔符&#xff0c;"\aa","\r\n"; 2.可以指定要发送对象的数据长度。 3.自己将数据打包。 …

力扣:有效的数独

文章目录 需求分析结尾 需求 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08…

2024年最新最全的【大模型学习路线规划】从零基础入门到精通!

2024年最新最全的大模型学习路线规划&#xff0c;对于零基础入门到精通的学习者来说&#xff0c;可以遵循以下阶段进行&#xff1a; 文章目录 一、基础准备阶段数学基础&#xff1a;编程语言&#xff1a;深度学习基础&#xff1a; 二、核心技术学习阶段Transformer模型&#xf…

第2章-04-Request Header与Response Header

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲,后续完整更新内容如下。 文章…

TortoiseGit使用教程

系列文章目录 文章目录 系列文章目录前言一、TortoiseGit下载安装二、使用步骤1.创建库1.需要上传的文件&#xff1a;不需要上传的文件&#xff1a; 2.拉取代码 前言 以前都是用svn&#xff0c;现在改用git Git是目前世界上最先进的分布式版本控制系统&#xff08;没有之一&am…