TCP滑动窗口、拥塞窗口

作者:wuxinliulei
链接:https://www.zhihu.com/question/32255109/answer/68558623
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

首先明确:
1)TCP滑动窗口分为接受窗口,发送窗口。
滑动窗口协议是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的。
对ACK的再认识,ack通常被理解为收到数据后给出的一个确认ACK,ACK包含两个非常重要的信息:
一是期望接收到的下一字节的序号n,该n代表接收方已经接收到了前n-1字节数据,此时如果接收方收到第n+1字节数据而不是第n字节数据,接收方是不会发送序号为n+2的ACK的。
举个例子,假如接收端收到1-1024字节,它会发送一个确认号为1025的ACK,但是接下来收到的是2049-3072,它是不会发送确认号为3072的ACK,而依旧发送1025的ACK。
二是当前的窗口大小m,如此发送方在接收到ACK包含的这两个数据后就可以计算出还可以发送多少字节的数据给对方,假定当前发送方已发送到第x字节,则可以发送的字节数就是y=m-(x-n).这就是滑动窗口控制流量的基本原理。
重点:发送方根据收到ACK当中的期望收到的下一个字节的序号n以及窗口m,还有当前已经发送的字节序号x,算出还可以发送的字节数。
发送端窗口的第一个字节序号一定是ACK中期望收到的下一个字节序号,比如下图:
在这里插入图片描述
上图52 53 54 55 字节都是可以新发送的字节序接受端窗口的第一个字节序之前一定是已经完全接收的,后面窗口里面的数据都是希望接受的,窗口后面的数据都是不希望接受的。http://blog.chinaunix.net/uid-20778955-id-539945.html
http://www.netis.com.cn/flows/2012/08/tcp-%E6%BB%91%E
5%8A%A8%E7%AA%97%E5%8F%A3%E7%9A%84%E7%AE%80%E4%BB%8B/

TCP的滑动窗口分为接收窗口和发送窗口,不分析这两种窗口就讨论是不妥当的。
TCP的滑动窗口主要有两个作用,一是提供TCP的可靠性,二是提供TCP的流控特性。同时滑动窗口机制还体现了TCP面向字节流的设计思路。TCP 段中窗口的相关字段。
在这里插入图片描述
TCP的Window是一个16bit位字段,它代表的是窗口的字节容量,也就是TCP的标准窗口最大为2^16-1=65535个字节。
另外在TCP的选项字段中还包含了一个TCP窗口扩大因子,option-kind为3,option-length为3个字节,option-data取值范围0-14。窗口扩大因子用来扩大TCP窗口,可把原来16bit的窗口,扩大为31bit。

滑动窗口基本原理

1)对于TCP会话的发送方,任何时候在其发送缓存内的数据都可以分为4类,“已经发送并得到对端ACK的”,“已经发送但还未收到对端ACK的”,“未发送但对端允许发送的”,“未发送且对端不允许发送”。“已经发送但还未收到对端ACK的”和“未发送但对端允许发送的”这两部分数据称之为发送窗口。
在这里插入图片描述
当收到接收方新的ACK对于发送窗口中后续字节的确认是,窗口滑动,滑动原理如下图。
在这里插入图片描述
当收到ACK=36时窗口滑动。
2)对于TCP的接收方,在某一时刻在它的接收缓存内存在3种。“已接收”,“未接收准备接收”,“未接收并未准备接收”(由于ACK直接由TCP协议栈回复,默认无应用延迟,不存在“已接收未回复ACK”)。其中“未接收准备接收”称之为接收窗口。

发送窗口与接收窗口关系

TCP是双工的协议,会话的双方都可以同时接收、发送数据。TCP会话的双方都各自维护一个“发送窗口”和一个“接收窗口”。其中各自的“接收窗口”大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。各自的“发送窗口”则要求取决于对端通告的“接收窗口”,要求相同。
在这里插入图片描述

滑动窗口实现面向流的可靠性

1)最基本的传输可靠性来源于“确认重传”机制。
2)TCP的滑动窗口的可靠性也是建立在“确认重传”基础上的。
3)发送窗口只有收到对端对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界4)接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。

滑动窗口的流控特性

TCP的滑动窗口是动态的,我们可以想象成小学常见的一个数学题,一个水池,体积V,每小时进水量V1,出水量V2。当水池满了就不允许再注入了,如果有个液压系统控制水池大小,那么就可以控制水的注入速率和量。这样的水池就类似TCP的窗口。应用根据自身的处理能力变化,通过本端TCP接收窗口大小控制来对对对端的发送窗口流量限制。应用程序在需要(如内存不足)时,通过API通知TCP协议栈缩小TCP的接收窗口。然后TCP协议栈在下个段发送时包含新的窗口大小通知给对端,对端按通知的窗口来改变发送窗口,以此达到减缓发送速率的目的。

滑动窗口和拥塞窗口的关系和区别

1.滑动窗口解决的是发送方和接收方接收数据速率不一致的问题,通过设置滑动窗口(可以通俗的理解为接收方的缓存)可以缓解这一个问题。具体的操作是接收方会向发送方通知自己可以接受数据的大小,而发送方会根据这个数值,发送数据。
2.拥塞窗口用控制全局网络的拥塞情况。通过控制发送方每次发送的流量的多少,用来逐渐试探整体网络的拥塞程度。如果没有拥塞控制,发送方每次发送的数据大小为滑动窗口,在只有2台主机的时候确实是没有问题的,但是如果放到现实的网络大环境中来说是行不通的。因为如果每台主机都发送的窗口大小的数据,那么整个网络系统必然会瘫痪。所以通过在发送方设置拥塞窗口,可以有效缓解网络压力。
————————————————
版权声明:本文为CSDN博主「yiqzq」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yiqzq/article/details/104114917

滑动窗口和拥塞窗口

一,滑动窗口

窗口:发送者发送的连续字节序列的集合
滑动:发送的窗口可以随发送过程而变化。
为什么需要窗口:不必每一个段进行一次确认应答,而是以一个窗口的大小进行确认。减少往返时间,提高速度。(TCP在发送时其实是以字节为单位的)

窗口控制和重发机制
1,数据已到达对端,但确认ack丢失,这种情况是不需要重发的。如果没有使用窗口机制则需要重发。某一个ack丢失,在窗口机制下可以通过下一个确认ack进行应答。在滑动窗口下,就算某些应答丢失也不会重发。
2,某个报文段丢失,一直重发发送确认ack。但对端该发送的还在发送。如果发送方连续收到3次同一个确认ack,就会重发数据。但是此时数据已经乱序了。这就是快速重发。

滑动窗口的功能
1,保证数据的可靠传递
未确认的数据必须被发送方缓存起来
确认的数据将会移除缓冲区
2,保证数据的有序传输
乱序的数据必须被接收方缓存起来
3,提供End-to-End的流控机制
发送方发送太快就必须阻塞等待

什么是流量控制
所谓流量控制,主要是接收方传递信息给发送方,使其不要发送数据太快,是一种端到端的控制。主要的方式就是返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送

流量控制的两个极端
一次发送一个字节(停等协议,效率极低)
发送拥有的所有数据(可能使接收方来不及接收,原端也无法尽快知道数据包的丢失)
TCP使用折中的方式:滑动窗口协议,发送方和接收方都有滑动窗口。

发送方滑动窗口
在这里插入图片描述

窗口移动
1,关闭,即窗口左边界右移。当已发送数据得到ack时,窗口会减小。
2,打开,右边界右移,使得可发送数据量增大。当确认数据得到处理,接收端可用缓冲区变大,窗口也随着变大。
3,收缩,窗口右边界右移,不允许这种做法。

一个字节探测包和0通告窗口
接收方发送了一个通告窗口为0的ACK,这种情况下发送方必须暂停发送数据,直到一个新的带非零窗口的通告(ACK)收到为止。
为了避免非零窗口的通告丢失,发送方在收到零窗口后启用persistence timer,发送1个字节的探测数据包,直到窗口重新打开为止。
注意
实际发送窗口大小是rwnd(接收端TCP报文的窗口大小字段)和cwnd(拥塞窗口大小)中的较小值。
源端并非必须要发送整个窗口大小的数据。

接收方滑动窗口:
在这里插入图片描述

第一部分,是已接收到了并确认的,但是还没被进程消耗。此时还需要占用接收缓冲区
第二部分,是接收窗口,接收后将会保存。
第三部分,不能接收。

二,拥塞窗口

拥塞:路由器因无法处理高速到达的流量而被迫丢弃数据信息的现象称为拥塞。
为什么有的流量控制,还需要拥塞控制?
流控只简单地表明了接收方的处理能力,并不能代表中间网络的处理能力
如果一开始把流控窗口内的数据全部发送出去,中间路由器可能一时处理不了如此多的突发流量
拥塞窗口(cwnd)和通告窗口(awnd)
实际的发送窗口:W=min(cwnd,awnd)。两者之间较小的。
如果接收方慢:W=awnd
如果网络慢:W=cwnd
拥塞控制算法:
慢启动
拥塞避免
超时重传
快速重发
快速恢复

慢启动:
初始化:cwnd=1mss;
以后每收到一个ack,cwnd+=1mss;
相当于指数增大
在这里插入图片描述

拥塞避免:
当cwnd超过ssthresh(慢启动阈值)时,每收到一个ack,cwnd+=1/cwnd;
相当于加法增大
超时重传:
cwnd越来越大,导致有包丢失。这时需要重传数据。
ssthresh=max(cwnd/2, 2) 这个的意思是cwnd/2 但是至少是2个报文段
cwnd=1,重新进入慢启动
下图为以上描述的整个过程
在这里插入图片描述
快速重传:
发送方收到3次重复的ack,就立即重传数据。
ssthresh=max(cwnd/2, 2);
快速恢复:
cwnd=ssthresh+3MSS;
每收到重复的ack,cwnd+=1MSS;
当收到新的ack时,cwnd重设为ssthresh,并退出快速恢复阶段。cwnd=ssthresh,然后进入加法增大(拥塞避免)
在这里插入图片描述

————————————————
版权声明:本文为CSDN博主「qq_33436509」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33436509/article/details/81979024

猜你喜欢

转载自blog.csdn.net/weixin_43956062/article/details/106376372