【JavaEE初阶】滑动窗口和流量控制以及拥塞控制

2024-08-24 09:04

本文主要是介绍【JavaEE初阶】滑动窗口和流量控制以及拥塞控制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

📕引言

🎄为什么出现滑动窗口

🎋滑动窗口丢包问题

🚩情况一:数据包已经抵达,ACK被丢了

🚩情况二:数据包就直接丢了

🌲流量控制(安全机制)

🌳拥塞控制(安全机制)


📕引言

前面我们讲到的确认应答,超时重传,连接管理都是用来保证TCP可靠传输的机制。那么TCP除了保证可靠传输之外,也希望能够尽可能的保证高效的完成数据传输。

🎄为什么出现滑动窗口

了解确认应答策略的人都知道,对每一个发送的数据报,都要给一个ACK确认应答。收到ACK后再发送下一个数据段。这样做有一个比较大的缺点,就是性能较差。尤其是数据往返的时间较长的时候。

这就是没有引入滑动窗口数据传输的过程,A这边每次要收到ACK才会发送下一个数据,大部分时间都消耗在等待上面了。

引入滑动窗口:

那我们就想,既然这样一发一收的方式性能较低,那么我们一次发送多条数据,就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)。虽然是批量发送,还是要等待一会儿ACK。

滑动窗口的理解:

窗口就相当于你一次能带饭的数量,TCP的窗口大小表示的是:

  • 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。上图的窗口大小就是4000
    个字节(四个段)。(窗口大小是可变,后序解释)

  • 发送前四个段的时候,不需要等待任何ACK,直接发送;

  • 收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据;依次类推;

  • 操作系统内核为了维护这个滑动窗口,需要开辟 ==发送缓冲区 ==来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉(后面丢包是会有作用)

  • 窗口越大,则网络的吞吐率就越高;

注意:假如当确认应答时,发送方收到的是3001,没有收到2001,这里没有冲突,意味着发送方对于3001之前的所有数据都得到了确认。那么此时滑动窗口就一下跳两格。

问题来了,如果出现了丢包,如何进行重传?

🎋滑动窗口丢包问题

滑动窗口虽然为了提升效率,但是前提是保证可靠传输。

我们这里分为两种情况来讨论

🚩情况一:数据包已经抵达,ACK被丢了

发送的数据包已经抵达,回应报文ACK却丢了

这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认;

这是因为ACK应答报文上的确认序列号表示的是,该字节序以前的报文一全部到达,请下一条报文从该字节序开始。

就比如上图中的1001丢了,但是收到了2001,也就代表2000以前的数据已经全部收到了。所以此时是否收到1001已经无所谓了

🚩情况二:数据包就直接丢了

比如下属情况,1-1000的数据包丢了

当1001-2000报文段丢失之后,虽然主机A一直在给主机B往后发送数据,但是接收端一直没有收到1001这段的数据报,就会一直向发送端索要1001的数据

发送端发现连续三次收到了接收端发来同样一个 “1001” 这样的应答,他就明白了这段数据丢了,就会将对应的数据 1001 -2000 重新发送;

这个时候接收端收到了 1001 之后,再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中;

结论:

滑动窗口说是"提升效率"的机制,更准确的说,是"亡羊补牢"的机制,TCP为了保证可靠性,牺牲了很多效率,引入滑动窗口,是效率上的牺牲变少一些,但是仍然是存在牺牲的,在怎么滑动窗口,速度不可能比UDP这种没有可靠机制的协议更快。

窗口大小是可变的,可以通过窗口大小,来控制发送方的速度,窗口越大,单位时间发送的数据越多,越高效,窗口越小,单位时间发送的数据越少。通常情况下,认为尽可能的高效传输,但是高效的前提是可靠,如果传输的速度太快,接收方处理不过来,此时也会引起丢包。

那么我们如何设置窗口的大小呢?这就不得不提到我们下面讲的两种机制:流量控制、拥塞控制

我们的窗口大小就是由这两个决定的,两者取最小

详细机制介绍如下所示:

🌲流量控制(安全机制)

接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。

因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制(Flow Control)

具体如何衡量接收方的处理速度呢?

接收方有一个接收缓冲区(阻塞队列):

就会把窗口大小的数值告诉发送方,如何告诉呢?接收方会返回ACK,在ACK的报文中,在TCP报头里,指定一个字段,表示上述的空间大小,这个字段这个是报头中的16位窗口大小。

发送方就可以按照上述窗口大小,决定下一轮数据发送的窗口大小了。

  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段,通过ACK端通知发送端;
  • 窗口大小字段越大,说明网络的吞吐量越高;
  • 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;
  • 发送端接受到这个窗口之后,就会减慢自己的发送速度;
  • 如果接收端缓冲区满了,就会将窗口置为0;这时发送方不再发送数据
  • 若B的缓冲区发生改变(应用程序消费了一部分数据),这时候需要发送方会定期发送一个窗口探测数据段(不携带载荷),从而触发ACK,知道B这边的缓冲情况,接收端把窗口大小告诉发送端。

🌳拥塞控制(安全机制)

拥塞控制和流量控制类似,都是和滑动窗口搭配的机制。

流量控制是站在接收方的角度从而影响发送方的速度。但是呢,发送方发得有多快,不光要考虑接收方的接收能力,还要考虑中间的路由器/交换机是否能接受。中间这些机器的处理能力是不确定的,链路上的任何一个节点,性能瓶颈都会制约发送方的发送速度。在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的。

流量控制的时候,很容易定量的来衡量接收缓冲区剩余空间的大小,这个作为发送窗口的大小。但是考虑中间节点就比较复杂,中间有多少设备?每次走的路径可能都不一样,每个设备的处理能力,繁忙程度都不一样......

那么我们就可以不管你中间结构有多复杂,tcp都把他们视为一个整体,然后通过"实验"的方式,找到一个合适的窗口大小(发送速度)。

流程:

具体流程:

TCP引入 慢启动 机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据;

  • 此处引入一个概念称为拥塞窗口
  • 发送开始的时候,定义拥塞窗口大小为1;
  • 每次收到一个ACK应答,拥塞窗口乘以2;
  • 每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口;

像上面这样的拥塞窗口增长速度,是指数级别的。

慢启动” 只是指初使窗口大小比较小,传输速度慢,但是增长速度非常快。

  • 为了不增长的那么快,因此不能使拥塞窗口单纯的加倍。
  • 此处引入一个叫做慢启动的阈值
  • 当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长
  • 线性增长也是增长,增长到一定程度,就会出现丢包,此时发送方就知道网络大概的能力是在啥样的水平,此时就会把窗口变小(发送速度减下去)

  • 直接缩到底(回到慢启动的时候),接下来指数增长-线性增长;缩到出现丢包的时窗口一半这样的位置,接下来线性增长
  • 当TCP开始启动的时候,慢启动阈值等于窗口最大值
  • 在每次超时重发的时候,慢启动阈值会变成原来最大窗口的一半,同时拥塞窗口置回1

注意:

  • 少量的丢包,我们仅仅是触发超时重传;大量的丢包,我们就认为网络拥塞;
  • 当TCP通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降;

最终流量控制的窗口大小和拥塞控制的窗口大小,谁小就取谁。

拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。

这篇关于【JavaEE初阶】滑动窗口和流量控制以及拥塞控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1102034

相关文章

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

Java docx4j高效处理Word文档的实战指南

《Javadocx4j高效处理Word文档的实战指南》对于需要在Java应用程序中生成、修改或处理Word文档的开发者来说,docx4j是一个强大而专业的选择,下面我们就来看看docx4j的具体使用... 目录引言一、环境准备与基础配置1.1 Maven依赖配置1.2 初始化测试类二、增强版文档操作示例2.

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

Spring Boot中的路径变量示例详解

《SpringBoot中的路径变量示例详解》SpringBoot中PathVariable通过@PathVariable注解实现URL参数与方法参数绑定,支持多参数接收、类型转换、可选参数、默认值及... 目录一. 基本用法与参数映射1.路径定义2.参数绑定&nhttp://www.chinasem.cnbs

JAVA中安装多个JDK的方法

《JAVA中安装多个JDK的方法》文章介绍了在Windows系统上安装多个JDK版本的方法,包括下载、安装路径修改、环境变量配置(JAVA_HOME和Path),并说明如何通过调整JAVA_HOME在... 首先去oracle官网下载好两个版本不同的jdk(需要登录Oracle账号,没有可以免费注册)下载完

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

Java中Integer128陷阱

《Java中Integer128陷阱》本文主要介绍了Java中Integer与int的区别及装箱拆箱机制,重点指出-128至127范围内的Integer值会复用缓存对象,导致==比较结果为true,下... 目录一、Integer和int的联系1.1 Integer和int的区别1.2 Integer和in

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.