【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协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。

  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值