0. 前言
从朋友分享的面经来看,TCP的拥塞机制在今年腾讯面试中被提及了,可见不论是什么研发岗位,计算机网络的知识总是那么的重要。本科时候学的都忘了=。= 今天打算总结TCP的流量控制和拥塞控制。网上查了下相关资料,发现都一模一样的,而且写的逻辑很乱。本篇对网上互相抄袭的版本进行精炼、补充,重点会用红字标出,逻辑就按照我理解的来写了,图就不自己画了。转载请注明出处:NetWork——TCP的流量控制和拥塞控制_SEU_Calvin的博客-CSDN博客。
1. TCP的流量控制
1.1 流量控制概述
首先我们得理解TCP为什么需要流量控制,或者说流量控制的意义何在?那就是如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。
TCP的流量控制是利用滑动窗口机制实现的,接收方在返回的ACK中会包含自己的接收窗口的大小,以控制发送方的数据发送。
1.2 流量控制实例
如上图所示A向B发送数据。在连接建立时,B告诉A接收窗口rwnd(receiver window)= 400字节,因此发送方A的发送窗口不能超过400。
(可以看出,B向A发送的三个报文段都设置了 ACK = 1以保证字段有效,后面的rwnd值就是接收方对发送方的三次流量控制。)
第一次把窗口设置为300 ,第二次100 ,最后一次为 0,即不允许发送方再发送数据的状态。假如,B向A发送了零窗口的报文段后不久,B的接收缓存又有了一些存储空间。于是B向A发送了rwind=400的报文段,然而这个报文段在传送中丢失了。就会出现A等待B确认,并且B等待A发送数据的死锁状态。为了解决这种问题,TCP引入了持续计时器(Persistence timer),当A收到零窗口通知时,就启用该计时器,时间到了则发送一个1字节的探测报文,询问B是很忙还是上个ACK丢失了,然后B回应自身的接收窗口大小,返回仍为0(A重设持续计时器继续等待)或者会重发rwnd=x。
2. TCP的拥塞控制
2.1 拥塞控制概述
我们仍然需要理解为什么需要拥塞控制。网络中的链路容量、交换结点中的缓存、处理机等等都有着工作的极限,当网络的需求超过它们的工作极限时,就出现了拥塞。拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。
2.2 慢开始(Slow-Start)和拥塞避免(Congestion Avoidance)结合
在这种机制中,发送方维护一个叫做拥塞窗口的变量,只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的数据发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的数据。
2.2.1 两种算法机制介绍
慢开始算法是指开始发送数据时,并不清楚网络的负荷情况,会先发送一个1字节的试探报文,当收到确认后,就发送2个字节的报文,继而4个,8个以此指数类推。
需要注意的是,慢开始的“慢”并不是指拥塞窗口的增长速率慢,而是指在TCP开始发送报文时先设置拥塞窗口=1。
拥塞避免算法是让拥塞窗口缓慢地增大,即cwnd加1,而不是如慢开始算法一样加倍。
2.2.2 两种算法的结合的实例分析
根据上图的实例进行分析,一开始的慢开始算法的指数增长是很恐怖的,所以为了防止拥塞窗口cwnd增长过快需要设置一个门限ssthresh,这里是16。
(1)当 cwnd < ssthresh 时,使用上述的慢开始算法。
(2)当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
(3)当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法。
无论在慢开始阶段还是在拥塞避免阶段,只要发送方没有收到确认,就认为这时候拥塞了,就要把慢开始门限ssthresh设置为此时发送方窗口值的一半(上例中是把发送方窗口值24修改为12)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。
这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。转载请注明出处为SEU_Calvin的博客。
2.3 快重传(Fast Retransmit)和快恢复(Fast Recovery)结合
快重传是指,如果发送端接收到3个以上的重复ACK,不需要等到重传定时器溢出就重新传递,所以叫做快速重传,而快速重传以后,因为走的不是慢启动而是拥塞避免算法,所以这又叫做快速恢复算法。
如果没有快速重传和快速恢复,TCP将会使用定时器来要求传输暂停。在暂停这段时间内,没有新的数据包被发送。所以快速重传和快速恢复旨在快速恢复丢失的数据包。
2.3.1 具体介绍
快重传的机制还是比较好理解的,如图所示,接收方发现M3丢失,则立即发送对M2的重复确认。一旦发送方一连收到三个M2的重复确认就应当立即重传M3,也就是发送方收到第四个对M2的确认时。
与快重传配合使用的还有快恢复算法,结合上图的实例来分析,其过程有以下两个要点:
(1)当发送方在cwnd=24时连续收到三个重复确认,就把慢开始门限ssthresh减半(就是上图中的24修改为12)。
(2)接下来不执行慢开始算法,而是把cwnd值设置为门限ssthresh减半后的数值(即cwnd不是设置为1而是设置为12),然后开始执行的是拥塞避免算法,使拥塞窗口缓慢地线性增大。
这里为什么替换掉了慢开始算法呢?
这是因为收到重复的ACK不仅仅告诉我们一个分组丢失了,由于接收方只有在收到另一个报文段时才会产生重复的ACK,所以还告诉我们该报文段已经进入了接收方的缓存。也就是说,在收发两端之间仍然有流动的数据,而我们不想执行慢启动来突然减少数据流。转载请注明出处为SEU_Calvin的博客。
关于TCP流量控制和拥塞控制的介绍至此结束,请大家多点赞支持~