滑动窗口算法

概述
滑动窗口实现了TCP流控制。首先明确滑动窗口的范畴:TCP是双工的协议,会话的双方都可以同时接收和发送数据。TCP会话的双方都各自维护一个发送窗口和一个接收窗口。各自的接收窗口大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。各自的发送窗口则要求取决于对端通告的接收窗口,要求相同。

滑动窗口解决的是流量控制的的问题,就是如果接收端和发送端对数据包的处理速度不同,如何让双方达成一致。接收端的缓存传输数据给应用层,但这个过程不一定是即时的,如果发送速度太快,会出现接收端数据overflow,流量控制解决的是这个问题。

窗口的概念
发送方的发送缓存内的数据都可以被分为4类:

  1. 已发送,已收到ACK
  2. 已发送,未收到ACK
  3. 未发送,但允许发送
  4. 未发送,但不允许发送

其中类型2和3都属于发送窗口。

接收方的缓存数据分为3类:

  1. 已接收
  2. 未接收但准备接收
  3. 未接收而且不准备接收

其中类型2属于接收窗口。

窗口大小代表了设备一次能从对端处理多少数据,之后再传给应用层。缓存传给应用层的数据不能是乱序的,窗口机制保证了这一点。现实中,应用层可能无法立刻从缓存中读取数据。

滑动机制
发送窗口只有收到发送窗口内字节的ACK确认,才会移动发送窗口的左边界。

接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。

遵循快速重传、累计确认、选择确认等规则。

发送方发的window size = 8192;就是接收端最多发送8192字节,这个8192一般就是发送方接收缓存的大小。

从上面的过程中,我们可以得到以下结论:

  1. TCP连接是通过数据包和ACK实现的,我们作为第三者可以看到双方发包的过程,但接受者在收到之前不知道发送方发的是什么,同样的,发送方在收到ACK前也不知道对方是否成功接收。

发送方没有收到接收方发回的ACK,就不能向右滑动。假设发送方向接收方发了ABCD就滑动,只要对方没收到A,就不能滑动,那么就会出现二者不同步的局面。

滑动窗口提高了信道利用率,TCP是发送报文段为单位的,假如每发一个报文就要等ACK,那么对于大数据包,等待时间就太长了。只要发送的报文在滑动窗口里面,不用等每个ACK回来就可以向右滑动。本例中,开始接收端空着AB,只有CD,此时不能滑动;之后接收到EF和H,直接向右滑动2位,不必等G到位。

窗口大小不能大于序号空间大小的一半。目的是为了不让两个窗口出现交迭,比如总大小为7,窗口大小都为4,接收窗口应当滑动4,但只剩3个序号,导致两个窗口相互迭代。

有一种情况没出现:发送方发ABCD,接收方都收到然后向右滑动,但回复的ACK包全丢了。发送方未收到任何ACK, timeout后会重发ABCD,此时的接收方按累计确认的原则,收到ABCD后只会重发D的ACK,发送方收到后向右滑动。

对比滑动窗口和拥塞窗口
滑动窗口是控制接收以及同步数据范围的,通知发送端目前接收的数据范围,用于流量控制,接收端使用。拥塞窗口是控制发送速率的,避免发的过多,发送端使用。因为tcp是全双工,所以两边都有滑动窗口。
两个窗口的维护是独立的,滑动窗口主要由接收方反馈缓存情况来维护,拥塞窗口主要由发送方的拥塞控制算法检测出的网络拥塞程度来决定的。

拥塞窗口控制sender向connection传输数据的速率,使这个速率为网络拥堵状况的函数。

找到一个经典的问题:

(一)给定一组大小为n的整数数组,计算长度为k的子数组和的最大值。

比如

数组为:1,2,3,4

最大值为:3+4=7

数组为:-1,4,7,-3,8,5,-2,6

最大值为:7-3+8=12

想到最简单思路,那就遍历所有子数组呗,求和然后比较。

    int index = 0;// 记录最大子数组第1个元素的索引,目前是0
    int maxSum = 0;// 记录最大子数组和,目前是从左开始第1个子数组
    for (int i = 0; i < k; i++) {
        maxSum += array[i];
    }

    for (int i = 1; i <= array.length - k; i++) {// 遍历所有子数组,求和并比较
        int curSum = 0;
        for (int j=0; j < k; j++) {// 计算当前子数组和
            curSum += array[i + j];
        }
        if (curSum > maxSum) {// 如果大于最大和,则记录
            maxSum = curSum;
            index = i;
        }
    }

运用滑动窗口思路,遍历时不嵌套循环计算所有值;外层遍历相当于窗口向右滑动,每次减去失效值加上最新值,即为当前窗口的和,然后再比较。

复制代码
int index = 0;// 记录最大子数组第1个元素的索引,目前是0
int maxSum = 0;// 记录最大子数组和,目前是从左开始第1个子数组
for (int i = 0; i < k; i++) {
maxSum += array[i];
}

    int curWindowSum = maxSum;
    for (int i = 1; i <= array.length - k; i++) {// 从下个元素开始,即窗口向右滑动
        curWindowSum = curWindowSum - array[i - 1] + array[k + i - 1];// 减去失效值,加上最新值
        if (curWindowSum > maxSum) {// 如果大于最大和,则记录
            maxSum = curWindowSum;
            index = i;
        }
    }

复制代码
可以看到代码差不多,只不过在计算求和时,采取了滑动窗口技术(思路),通过一减一加求和,消除了内部的循环。
注:这里为了突出语义,将变量名curSum改为curWindowSum

原文地址:https://blog.51cto.com/1348916/2450194

时间: 2024-10-11 19:16:01

滑动窗口算法的相关文章

LeetCode-Minimum Window Substring-最小窗口子串-滑动窗口算法(尺取法)

https://oj.leetcode.com/problems/minimum-window-substring/ 线性复杂度的限制下,考虑使用滑动窗口法.这个方法的思路就是维持一个窗口,窗口向右边界扩张以满足限制条件.窗口左边界收缩以尽量使其最小. 注意这个题目可能是一个典型的滑动窗口方法的实现.外部循环移动左边界i,循环内部扩张右边界p以满足限制条件.并且内外都有终止可能. 使用两个map和一个计数变量以快速统计条件限制的满足情况. class Solution { public: int

第二十六节,滑动窗口和 Bounding Box 预测

上节,我们学习了如何通过卷积网络实现滑动窗口对象检测算法,但效率很低.这节我们讲讲如何在卷积层上应用这个算法. 为了构建滑动窗口的卷积应用,首先要知道如何把神经网络的全连接层转化成卷积层.我们先讲解这部分内容,并演示卷积的应用过程. 一 卷积的滑动窗口实现 假设对象检测算法输入一个 14×14×3 的图像,图像很小,不过演示起来方便.在这里过滤器大小为 5×5,数量是 16, 14×14×3 的图像在过滤器处理之后映射为 10×10×16.然后通过参数为 2×2 的最大池化操作,图像减小到 5×

2. 滑动窗口和 Bounding Box 预测

滑动窗口和 Bounding Box 预测(转) 原文链接:https://www.cnblogs.com/zyly/p/9180485.html 目录 一 卷积的滑动窗口实现 二  Bounding Box 预测 上节,我们学习了如何通过卷积网络实现滑动窗口对象检测算法,但效率很低.这节我们讲讲如何在卷积层上应用这个算法. 为了构建滑动窗口的卷积应用,首先要知道如何把神经网络的全连接层转化成卷积层.我们先讲解这部分内容,并演示卷积的应用过程. 回到顶部 一 卷积的滑动窗口实现 假设对象检测算法

TCP数据量--滑动窗口、拥塞窗口、慢启动、Negle算法 经受时延的确认等

TCP的数据流大致可以分为两类,交互数据流与成块的数据流.交互数据流就是发送控制命令的数据流,比如relogin,telnet,ftp命令等等:成块数据流是用来发送数据的包,网络上大部分的TCP包都是这种包. 很明显,TCP在传输这两种类型的包时的效率是不一样的,因此为了提高TCP的传输效率,应该对这两种类型的包采用不同的算法. 总之,TCP的传输原则是尽量减少小分组传输的数量. TCP的交互式数据流 ?         经受时延的确认技术 TCP的交互式数据流通常使用"经过时延的确认"

算法设计与优化策略——滑动窗口

"滑动窗口"和上篇博客中介绍的"等价转换"一样也为一种算法优化的思想.同样,下面通过一个例子,来介绍这种思想.唯一的雪花(Unique snowflake,UVa 11572)输入一个长度为n(n<=10^6)的序列A,找到一个尽量长的连续子序列AL~AR,使得该序列中没有相同的元素.在读完题目以后,我们不难有思路.最简单的思路就是,我们可以通过循环的方法,对每一个元素都找出一它为开头的最长序列(没有相同元素).这个方法也能做出来,但似乎有点太麻烦了.下面,我

粘包、拆包发生原因滑动窗口、MSS/MTU限制、Nagle算法

[TCP协议](3)---TCP粘包黏包 有关TCP协议之前写过两篇博客: 1.[TCP协议](1)---TCP协议详解 2.[TCP协议](2)---TCP三次握手和四次挥手 一.TCP粘包.拆包图解 假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数是不确定的,故可能存在以下四种情况: 1)服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包 2)服务端一次接受到了两个数据包,D1和D2粘合在一起,称之为TCP粘包 3)服务端分两次读取到了数据包,

第二十四个知识点:描述一个二进制m组的滑动窗口指数算法

第二十四个知识点:描述一个二进制m组的滑动窗口指数算法 简单回顾一下我们知道的. 大量的密码学算法的大数是基于指数问题的安全性,例如RSA或者DH算法.因此,现代密码学需要大指数模幂算法的有效实现.我们应该从一个简化的方案开始思考:计算\(x^a\mod N\),我们可以用指数算法来求\(x^a\),然后再约减到\(N\).然而,对大多数密码算法来说,\(x^a\)都是非常大的.现在,大多数传统的方法能被简单的在每个阶段模\(N\).这回产生一些改进的技术.下面我会介绍一些计算\(X^E \mo

算法--滑动窗口

转载请标明出处http://www.cnblogs.com/haozhengfei/p/a14049ec0869a8125a69f3af37471c77.html 滑动窗口练习题 第8节 滑动窗口练习题 有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置. 返回一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值. 以数组为[4,3,5,4,3,3,6,7],w=3为例.因为第一个窗口[4,3,5]的最大值为5,第二个窗口[3

算法题解之滑动窗口

Substring with Concatenation of All Words 寻找所有词连接的子串 思路:由于该字串是所有词典中的词连接的,所以该字串长度固定.因此本题可以看作一个滑动窗口的题.为了去除重复工作,每次滑动一个单词的长度,因此起始位置就有n种(n为单词长度).每种起始位置的滑动策略如下: 如果当前窗口满足条件,则窗口只往后移动一个单词,并且下一次只检查最后一个单词(中间的单词肯定满足条件).    如果当前窗口不满足条件,则有两种情况: 1.当前窗口内不满足条件的第一个单词不