首先介绍一下,什么是网络拥塞:简单点说,就是网络中的Tcp连接太多,此时对于网络中资源的需求量很大,大于了网络中的可用资源,比如网络中的链路容量、路由器的缓存等等。对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏,这种情况就叫做拥塞。 若网络中有许多资源同时呈现供应不足,网络的性能就会明显变坏,整个网络的吞吐量将随着输入负荷的增大而下降。
引起网络拥塞的条件可写为如下关系式:
发生网络拥塞常常趋于恶化。如果一个路由器没有足够的缓存空间,新到达该节点的分组因无存储空间暂存,它就会丢弃一些新到的分组。但当分组被丢弃时,由于Tcp的重传机制,发送这一分组的源点就会重传这一分组,甚至可能还要重传多次。这样会引起更多的分组流入网络和被网络中的路由器丢弃,这样会加剧对网络资源的消耗,在网络中传输的数据会更多。可见拥塞引起的重传并不会缓解网络的拥塞,反而会加剧网络的拥塞。
拥塞控制:拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至于过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及所有的主机、路由器,以及与降低网络传输性能有关的所有因素。
下图为拥塞控制所能起到的作用:
横坐标是提供的负载,代表单位时间内输入给网路的分组数目。纵坐标是吞吐量,代表单位时间内从网络输出的分组数目。
由图可以看出,如果没有加入拥塞控制,那么当提供的负载达到某一数值时,网络的吞吐量会随着提供的负载的增大而下降,这时网络就进入了拥塞状态。当提供的负载继续增大到某一数值时,网络的吞吐量就下降到零,网络就已经无法工作,这就是所谓的死锁。也就是网络瘫痪。
通过以上的分析,大家应该都知道了什么是网络拥塞,为什么会发生网络拥塞,网络拥塞会给网络带来什么影响了。那么接下来,就分析一下如何避免出现网络拥塞,下面我就介绍几种拥塞控制的方法。
拥塞控制的方法:慢开始、拥塞避免、快重传、快恢复。
在介绍这些算法的原理前,我们先假定:
1、数据是单方向传送,而另一个方向只传送Tcp中的确认报文ACK。
2、接受方总是有足够大的缓存空间,因而发送窗口的大小由网络的拥塞程度来决定,也就是发送窗口由拥塞窗口来决定。(如果考虑到接受方的缓存空间大小,那么有可能发送窗口还要比拥塞窗口小一些,发送窗口 = min(接受窗口,拥塞窗口),这样才能确保每一次发送给接收方的数据,接收方的缓存空间有能力接收到这些数据。)
NO.1: 慢开始和拥塞避免
慢开始算法思路: 当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。 慢开始算法则是由小到大逐渐增大拥塞窗口数值,刚开始发送报文段时,先把拥塞窗口设置为一个最大报文段MSS的数值。在每次收到前一组最后一个报文段的确认后,翻倍增加拥塞窗口的数值,用这样的方法逐步增大发送方拥塞窗口的值。
在慢开始算法中刚开始发送报文段的时候,先设置拥塞窗口cwnd = 1,使得发送方在开始时只发送一个报文段,目的是试探一下网络的拥塞情况,然后再逐渐增大cwnd。这对于防止网络出现拥塞是一个非常有力的措施。 在cwnd逐渐翻倍增大的过程中,为了防止拥塞窗口cwnd增长过大引起网络拥塞,又设置了一个慢开始门限值ssthresh,慢开始门限ssthresh的用法如下:
当cwnd < ssthresh 时,使用慢开始算法。
当cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
当cwnd = ssthresh 时,即可使用慢开始算法,也可使用拥塞避免算法。
拥塞避免算法思路: 让发送方的拥塞窗口cwnd缓慢的增大,即每次收到上次发送全部数据的确认信息后,把发送方的拥塞窗口cwnd加1,而不是加倍。这样,拥塞窗口cwnd按线性规律缓慢增大,比慢开始算法的拥塞窗口增长速率缓慢的多。
注意:拥塞避免,并非指完全能够避免了拥塞,利用以上得措施要完全避免网络拥塞还是不可能得。拥塞避免是说在拥塞避免阶段将拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞。
NO.2:快重传和快恢复
快重传算法思想:当接收方收到一个失序的报文段后就立即发出对上一个报文段的重复确认,为的是让发送方及早知道有报文段没有到达接收方。如果发送方收到了关于一个报文的四次确认,也就是有三次是重复确认,就应当立即重传对方尚未收到的报文段,而不必继续等待为这个未到达的报文段设置的重传计时器到期。由于发送方能尽早重传未被确认的报文段,因此采用快重传后可以使整个网络的吞吐量提高约20%。
下图为快重传的示意图:
依据上图简单的说,快重传就是当收到连续三个对于报文段M2的重复确认,就立即重传丢失的M3报文段,而不需要等待为M3设置的重传计时器到期再去重传M3。
与快重传配合使用的是快恢复算法,快恢复算法过程主要是以下两点:
1、当发送方连续收到三个重复的确认后,就执行“乘法减小”算法,把慢开始门限值ssthresh设置为当前拥塞窗口的一半。这是为了预防网络发生阻塞。(注意,接下来不去执行慢开始算法)
2、发送方收到连续的三个重复确认,并不会认为此时发生了网络拥塞。因为如果网络发生了严重的拥塞,就不会有好几个报文段会发送给接收方,也不会收到接收方的三个重复确认。因此,接下来并不执行慢开始算法,而是把cwnd拥塞窗口的值设置为更新后的慢开始门限ssthresh的数值,然后执行拥塞避免算法,加法增加拥塞窗口的值。
采用了快恢复算法时,慢开始算法只是在TCP连接建立时和网络出现超时时才使用。 如果只是发送报文段过程中,有报文段丢失,而此时网络并没有拥塞,那么就采用快恢复算法提高网络中传输数据的性能。
(个人认为,中途有一个报文段丢失,可能只是某一个路由器的缓存满了,所以丢掉了新来的这个报文段。 因为在现在的链路连接中很难发生报文段因为硬件的原因而丢失)
现在的快重传实现其实是把快恢复要用到的拥塞窗口cwnd再增大三个报文段的大小,即为 ssthresh +3 * MSS。因为既然发送方可以接收到三个重复的确认,就表明已经有三个分组离开了网络,成功到达了接收方的接受缓冲区中,现在这三个分组不再消耗网络的资源,所以可以适当的将拥塞窗口扩大一些。(要立即重传的这个报文段的后三个报文段已经成功发送到了接收方的接收缓冲区中,不再占用网络资源。)
下图为当连续收到三个重复的确认后,采用快重传和快恢复实现拥塞避免的示意图:
总结:
在TCP刚连接上时发送数据采用慢开始算法发送数据,在没有发生网络拥塞情况下,当达到了设置的慢开始门限值的时候采用拥塞避免算法发送数据。无论是在慢开始阶段还是在拥塞避免阶段,只要发送了网络拥塞,就直接使用慢开始算法,将新的慢开始门限值设置为发生拥塞时拥塞窗口值的一半,并从一次只发送1个报文段数据开始发送数据,使用慢开始算法。
如果在没有发生拥塞的情况下,发送方这边收到了连续三个重复的确认报文ACK,说明发生了丢包,在接收方这边发现接收到的报文段乱序,就直接给发送方发送上一次接收到报文段的确认,正如上述的第三张图。这时发送方发现这并不可能是网络拥塞,于是就使用快重传将在网络中丢掉的报文段立即重传,而不会等待超时重传设置的时间到了才去处理。然后使用快恢复算法,将发送方的慢开始门限值ssthresh设置为当前拥塞窗口的一半,并将拥塞窗口也设置为这个新的门限值大小(并不会使用慢开始算法,所以叫做快恢复),然后开始使用拥塞避免算法线性的增加拥塞窗口的大小。采用快恢复相比较慢开始可以提高网络资源的利用率,提高吞吐量。