IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 滑动窗口和拥塞窗口 -> 正文阅读

[网络协议]滑动窗口和拥塞窗口

滑动窗口和拥塞窗口

(1)窗口分为滑动窗口和拥塞窗口

  • 滑动窗口是接受数据端使用的窗口大小,用来告知发送端接收端的缓存大小,以此可以控制发送端发送数据的大小,从而达到流量控制的目的。
  • 拥塞窗口是数据的发送端,拥塞窗口不代表缓存,拥塞窗口指某一源端数据流在一个RTT内可以最多发送数据包

(2)实现一个靠谱的协议:TCP 协议使用的也是同样的模式。为了保证顺序性,每一个包都有一个 ID。在建立连接的时候,会商定起始的 ID 是什么,然后按照 ID 一个个发送。为了保证不丢包,对于发送的包都要进行应答,但是这个应答也不是一个一个来的,而是会应答某个之前的 ID,表示都收到了,这种模式称为累计确认或者累计应答(cumulative acknowledgment),目的是节省时间,提高效率!

ACK:通常被理解为收到数据后给出的一个确认ACK

  • 一是期望接收到的下一字节的序号n,该n代表接收方已经接收到了前n-1字节数据
  • 二是当前的窗口大小m,假定当前发送方已发送到第x字节,则可以发送的字节数就是y=m-(x-n).这就是滑动窗口控制流量的基本原理.

**解决的问题:**发送端的缓存里是按照包的ID一个个排列的。 因为TCP协议是全双工通信协议。 所以客户端既是发送端,也是接收端。 服务器端既是接收端,也是发送端。 所以客户端既有发送端缓存,也有接收端缓存。 而服务器端既有接收端缓存,也有发送端缓存。

滑动窗口包含:已发送未反馈+准备发送但未发送的数据。

发送端:

发送端缓存会被分为4部分:

  • 第一部分,已经发送并且已经确认的包
  • 第二部分,已经发送但是尚未确认的包
  • 第三部分,尚未发送但是马上准备发送的包
  • 第四部分,尚未发送但是暂时不准备发送的包。

其中:

  • LastByteAcked:第一部分和第二部分的分界线
  • LastByteSent:第二部分和第三部分的分界线

请添加图片描述

ex:滑动窗口大小:12-4+1=9; 已经发送到:9 希望接受的下一序号:10

则可以发送的数据=12-10+1=3

我们使用三个术语来描述窗口左右边沿的运动:

  • 窗口左边沿向右边沿靠近为窗口合拢。
    • 这种现象发生在数据被发送和确认时。
  • 当窗口右边沿向右移动时将允许发送更多的数据,我们称之为窗口张开。
    • 这种现象发生在另一端的接收进程读取已经确认的数据并释放了TCP的接收缓存时

当接收端的缓冲区满了,发送端接收到接收端的窗口大小为0,这个时候停止发送数据,这个时候发送端会过了超时重发的时间,发送一个窗口探测的包,此数据端仅含一个字节以获取最新的窗口大小信息

接收端:

  • 第一部分:接受并且确认过的
  • 第二部分:还没接收,但是马上就能接收的
  • 第三部分:还没接收,也没法接收的。

其中:

  • MaxRcvBuffer:最大缓存的量;
  • LastByteRead: 之后是已经接收了,但是还没被应用层读取的;
  • NextByteExpected :是第一部分和第二部分的分界线。

请添加图片描述

联系发送端和接收端看:

(1)1、2、3 没有问题,双方达成了一致。

(2)4、5 接收方说 ACK 了,但是发送方还没收到,有可能丢了,有可能在路上。

(3)6、7、8、9 肯定都发了,但是 8、9 已经到了,但是 6、7 没到,出现了乱序,缓存着但是没办法 ACK。

根据以上状态引入几个知识点:

  • 确认与重发的机制
    • 发送包丢失或ACK包其中一方丢失,都会导致重传。实际场景是:假设 4 的确认到了,不幸的是,5 的 ACK 丢了,6、7 的数据包丢了。
      • 超时重试:每一个发送了,但是没有 ACK 的包,都有设一个定时器,超过了一定的时间,就重新尝试。
      • 重试时间:数据包重传需要一个算法去计算超时的时间,时间太短的话包还没发送到就丢了,需要重新传,时间太长的话访问会变慢,时间必须大于往返时间 RTT
      • 在重传时间也就是往返的RTT的估计中引入自适应重传算法(Adaptive Retransmission Algorithm):估计往返时间,需要 TCP 通过采样 RTT 的时间,然后进行加权平均,算出一个值,而且这个值还是要不断变化的,因为网络状况不断地变化。除了采样 RTT,还要采样 RTT 的波动范围,计算出一个估计的超时时间。
  • TCP对于超时的策略是:超时间隔加倍,每当遇到一次超时重传的时候,都会将下一次超时时间间隔设置为先前值的两倍,两次超时,说明网络环境差,不宜频繁反复的发送
  • 快速重传的机制:当接收方收到一个序号大于下一个所期望的报文段时,就会检测到数据流中的一个间隔,于是它就会发送冗余的 ACK,仍然 ACK 的是期望接收的报文段。而当客户端收到三个冗余的 ACK 后,就会在定时器过期之前,重传丢失的报文段。

ex:

超时重传及时间:如果过一段时间,5、6、7 都超时了,就会重新发送。接收方发现 5 原来接收过,于是丢弃 5;6 收到了,发送 ACK,要求下一个是 7,7 不幸又丢了。当 7 再次超时的时候,有需要重传的时候,TCP 的策略是超时间隔加倍。每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。

快速重传:接收方发现 6 收到了,8 也收到了,但是 7 还没来,那肯定是丢了,于是发送 6 的 ACK,要求下一个是 7。接下来,收到后续的包,仍然发送 6 的 ACK,要求下一个是 7。当客户端收到 3 个重复 ACK,就会发现 7 的确丢了,不等超时,马上重发。

区别:

  • 快速重传:由接收端控制的,接收端会反复告诉发送端,我需要前面的包,中间丢了一个。
  • 超时重传:发送端在超过定时器的时间间隔后没有接到已发包的ack确认,超时重发。

流量控制问题

发送端发送的每一个数据包,服务端都要给一个确认包(ACK).确认它收到了。 服务端给发送端发送的确认包(ACK包)中,同时会携带一个窗口的大小。

窗口大小 = 接收端最大缓存量 - 接收已确认但还未被应用层读取的部分

发送窗口大小和接受窗口应用层读取的速度有关

  • 读取速度>窗口 窗口会不断变大
  • 读取速度<窗口 窗口会不断变小,极端情况下为0
  • 读取速度=窗口 窗口不变

拥塞控制问题

发送未确认<={cwnd, rwnd}

Advertised window:接收端给发送端报的窗口大小,滑动窗口包含:已发送未反馈,准备发送但未发送的数据。

rwnd:receiver window,接收方滑动窗口,用于防止接收方缓存占满

cwnd:congestion window,拥塞窗口,用于控制将带宽占完也就是怕把网络塞满

TCP 的拥塞控制主要来避免两种现象

  • 包丢失
  • 超时重传

ex:如图所示,假设往返时间为 8s,去 4s,回 4s,每秒发送一个包,每个包 1024byte。已经过去了 8s,则 8 个包都发出去了,其中前 4 个包已经到达接收端,但是 ACK 还没有返回,不能算发送成功。5-8 后四个包还在路上,还没被接收。这个时候,整个管道正好撑满,在发送端,已发送未确认的为 8 个包,正好等于带宽,也即每秒发送 1 个包,乘以来回时间 8s。
请添加图片描述

如果我们在这个基础上再调大窗口,使得单位时间内更多的包可以发送,原来发送一个包,从一端到达另一端,假设一共经过四个设备,每个设备处理一个包时间耗费 1s,所以到达另一端需要耗费 4s,如果发送的更加快速,则单位时间内,会有更多的包到达这些中间设备,这些设备还是只能每秒处理一个包的话,多出来的包就会丢失,这是我们不想看到的。这个时候,我们可以想其他的办法,例如这个四个设备本来每秒处理一个包,但是我们在这些设备上加缓存,处理不过来的在队列里面排着,这样包就不会丢失,但是缺点是会增加时延,这个缓存的包,4s 肯定到达不了接收端了,如果时延达到一定程度,就会超时重传,也是我们不想看到的。

拥塞窗口大小控制原则:

  • 一条 TCP 连接开始,cwnd 设置为一个报文段,一次只能发送一个,之后2,4,8,16…可以看出这是指数性的增长。

  • 涨到一个值 ssthresh 为 65535 个字节,当超过这个值的时候,就要改成线性增长。每收到一个确认后,cwnd 增加 1/cwnd。

出现拥塞之后重传方案:

  • 拥塞的一种表现形式是丢包,需要超时重传,这个时候,将 sshresh 设为 cwnd/2,将 cwnd 设为 1,重新开始慢启动。这真是一旦超时重传,马上回到解放前。但是这种方式太激进了,将一个高速的传输速度一下子停了下来,会造成网络卡顿。
  • 前面我们讲过快速重传算法。当接收端发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,cwnd 减半为 cwnd/2,然后 sshthresh = cwnd,当三个包返回的时候,cwnd = sshthresh + 3,也就是没有一夜回到解放前,而是还在比较高的值,呈线性增长。

请添加图片描述
但是以上拥塞控制存在两个问题:

  • 丢包并不代表着通道满,例如公网上带宽不满也会丢包,这个时候就认为拥塞了,退缩了,其实是不对的。
  • TCP 的拥塞控制要等到将中间设备都填充满了,才发生丢包,从而降低速度,这时候已经晚了。其实 TCP 只要填满管道就可以了,不应该接着填,直到连缓存也填满。

为了解决以上问题引入了TCP BBR 拥塞算法。它企图找到一个平衡点,就是通过不断地加快发送速度,将管道填满,但是不要填满中间设备的缓存,因为这样时延会增加,在这个平衡点可以很好的达到高带宽和低时延的平衡。

总结

  • 顺序问题、丢包问题、流量控制都是通过滑动窗口来解决的、

    • 顺序问题,重传
    • 丢包问题,重传
    • 流量控制,包的确认中,同时会携带一个窗口的大小,如果这时候接收端缓存中的接受已确认一直不被应用层拿走,那么,就会使得等待接受未确认的窗口变为0,就会给发送端发送窗口为0。
  • 拥塞控制是通过拥塞窗口来解决的,相当于往管道里面倒水,快了容易溢出,慢了浪费带宽,要摸着石头过河,找到最优值。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章           查看所有文章
加:2021-09-08 11:06:18  更:2021-09-08 11:08:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 10:22:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计