热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

计算机网络_计算机网络之TCP协议流量拥塞控制算法原理:滑动窗口cwnd与rwnd

篇首语:本文由编程笔记#小编为大家整理,主要介绍了计算机网络之TCP协议流量拥塞控制算法原理:滑动窗口cwnd与rwnd相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了计算机网络之TCP协议流量拥塞控制算法原理:滑动窗口cwnd与rwnd相关的知识,希望对你有一定的参考价值。






一、前言

  这篇博客来讲讲TCP的拥塞控制机制,这是TCP中比较复杂的一个部分,它与TCP的很多内容都有关联,但是这里不可能将这些内容都说一遍,所以以下描述将建立在读者对TCP的机制有一定了解的基础之上。这一部分内容确实有些复杂,我尽量在少涉及TCP其他内容的条件下将它叙述清楚。

 

二、正文

 2.1 什么是拥塞控制

  我们都知道,网络错综复杂,在这个复杂的网络中,很少有两台主机是直接相连。尽管如此,我们还是可以通过网络与其他主机通信,这是为什么?因为我们发送到网络中的数据,当达到网络中的一个节点时(假设是路由器),它会根据数据包含的地址,帮我们将数据转发到离目的地更近的路由器,或直接转发到目的地。但是,这些路由器不是直接就可以转发的,它们需要先将接收到的数据放入自己的内存(可能还要做一些处理),再从中取出进行转发。

  这里就面临一个问题:路由器的内存是有限的,若同一时间到达某个路由器的数据太多,这个路由器将无法接收所有的数据,只能将一部分丢弃;或者同一台路由器数据太多,后面到达的数据将要等待较长的时间才会被转发。网络中的数据太多,导致某个路由器处理不过来或处理地太慢,这就是网络拥塞。若是对于TCP这种有重传机制的传输协议,当发生数据丢失时,重传数据将延长数据到达的时间;同时,高频率的重传,也将导致网络的拥塞得不到缓解。拥塞控制,就是在网络中发生拥塞时,减少向网络中发送数据的速度,防止造成恶性循环;同时在网络空闲时,提高发送数据的速度,最大限度地利用网络资源。说的简单点,就和堵车差不多,路就这么宽,来的车多了,自然过的就慢,所以在必要的时候要限号。

 

 2.2 拥塞控制的方法

  在理论中,拥塞控制有两种实现方式:


  • 端到端拥塞控制:在这种拥塞控制方法中,由发送数据的端系统自己来判断是否拥塞,然后调整传输速率。比如说发送的数据已经超时却还没有接收到确认报文,数据往返时延过高,接收到对同一个数据段的重复确认......都可以认为是网络拥塞的现象;若发送端检测到这种现象,就应该降低发送数据的速率,若没有,则可以慢慢提高速率;
  • 网络辅助的拥塞控制:由网络中的路由器来告诉发送方,网络的拥塞情况。一般有两种方式:(1)路由器直接向发送端发送报文,告知网络拥塞情况;(2)路由器更改数据段中的某个标志,来提示网络中的拥塞情况,然后数据将这个标志携带到目的主机,再由目的主机根据这个标志,向发送端发送报文,告知拥塞情况(被包含在确认报文中);

 

 2.3 TCP的拥塞控制方法

  因为网络层不会提供拥塞的反馈信息,所以TCP协议采用的是第一种方式——自己判断网络的拥塞情况。当TCP检测到网络拥塞,则降低数据的发送速率,否则增加数据的发送速率。这里就将面临三个问题:


  1. TCP如何限制数据的发送速率;
  2. TCP如何检测网络中是否拥塞;
  3. TCP采用什么算法来调整速率(什么时候调整,调整多少);

  首先来回答第一个问题。了解TCP的应该知道,TCP不是发送一个数据段,接收到确认后再发送另一个数据段,它采用的是流水线的方式。TCP的每一个数据段都有一个序号,而TCP维护一个发送窗口来发送是数据,这个窗口就是一个区间。所有序号位于这个窗口内的数据段都会被一次性发送,而不需要等待之前发送的数据段被确认。而每当最早发送出去的数据段被确认,窗口就会向前移动,直到移动到第一个没有被确认的序号,这时候又会有新的数据段序号被包含在窗口中,然后被发送出去。所以限制数据发送速率最好的方式就是限制窗口的大小。在发送方的TCP程序会跟踪和维护一个叫做拥塞窗口的变量,用来进行拥塞控制。拥塞窗口被称为cwnd。在TCP发送端,所有被发送但是还没收到确认的数据段必须落在这个窗口中,所有,当网络拥塞时,TCP程序将减小cwnd,而网络通畅时,增大cwnd,以此来控制数据发送的速率。

  接着来回答第二个问题。TCP程序将通过数据发送的一些现象来推测网络是否拥塞,比如:


  • 若发送一条数据段后,成功接收到了接收方的确认报文,则可以认为网络没有拥塞;
  • 若发送出一条数据段后,在规定时间内没有收到确认报文(丢失或时延太大),则可以认为网络出现了拥塞;
  • 若连续收到接收方对同一条报文的三次冗余确认(也就是四次确认),则可以推测那条报文丢失,即发生了拥塞;

  上面的第三种情况,与TCP的快速重传机制有关,我这里不详细说明,只是大致介绍一下。TCP无法保证数据能够按顺序到达接收端,所以,可能出现序号靠后的数据报反倒先到达的情况。而TCP接收方并不是接收到哪一条报文,就向发送方发送哪条报文的确认,它是通过发送当前应该接收到的序号最小的报文进行确认。举个例子:


  1. 发送方同时发送了1,2,3,4,5这五个序号的报文,假设接收方接收到序号1的报文,于是将向发送方发送一个确认号为2的确认报文(TCP发送方通过确认号来判断接收方接收到的报文),告诉发送方我已经收到2之前的报文了,下一条报文我想要2;
  2. 接收方接收到2号报文后,发送确认号3,告诉发送方我接收到了3之前的所有报文;
  3. 这时候因为网络的不确定性,在3号没有到达前,4号报文先到达了,接收方接收到后,将它放入缓存,并依旧回复确认号3,表示它需要的是3号报文;
  4. 可是,之后到达的却5,于是它将5放入缓存,并依旧回复3;
  5. 直到3迟迟的到来,这时候接收方接收3,同时发现缓存中存在4和5,于是回复发送方确认号6,表示自己已经接收到了6之前的全部报文,下一条需要6;

  在这里,发送方一共接收到了三条确认号为3的确认报文(确认号为3是对2号报文的确认),第一条正常,后面两条冗余。而所谓的快速重传就是指:若发送方接收到对同一条报文的三次冗余确认(也就是四次确认),就认为这条报文的下一条已经丢失,于是不管计时器是否超时,都直接重传这条报文的下一条。上面的例子中,2号报文被冗余确认了两次,还不构成快速重传的条件。而为什么是三次,其实就是概率和时间长短的折中选择。

  下面回到正题,当快速重传的条件发生,发送方将认为出现了拥塞导致丢包。所有归根到底,TCP判断拥塞的方式就是检测有没有丢包。于是我们就可以回答第三个问题了,TCP如何调整发送速率——在没有丢包时慢慢提高拥塞窗口cwnd的大小,当发生丢包事件时,减少cwnd的大小。当然,具体的算法要复杂的多,TCP调整拥塞窗口的主要算法有 慢启动 , 拥塞避免 以及 快速恢复,其中前两个是TCP规范要求必须实现的,而第三个则是推荐实现的,TCP根据情况在这三者之间切换。 下面我就来一一介绍。

 

 2.4 慢启动

  在讲解之前,首先得知道一些名词:


  • MSS:最大报文段长度,TCP双方发送的报文段中,包含的数据部分的最大字节数;
  • cwnd:拥塞窗口,TCP发送但还没有得到确认的报文的序号都在这个区间;
  • RTT:往返时间,发送方发送一个报文,到接收这个报文的确认报文所经历的时间;
  • ssthresh:慢启动阈值,慢启动阶段,若cwnd的大小达到这个值,将转换到拥塞避免模式;

  慢启动是建立TCP连接后,采用的第一个调整发送速率的算法(或叫模式)。在这个阶段,cwnd通常被初始化为1MSS,这个值比较小,在这个时候,网络一般还有足够的富余,而慢启动的目的就是尽快找到上限。在慢启动阶段,发送方每接收到一个确认报文,就会将cwnd增加1MSS的大小,于是:


  • 初始cwnd=1MSS,所以可以发送一个TCP最大报文段,成功确认后,cwnd = 2MSS;
  • 此时可以发送两个TCP最大报文段,成功接收后,cwnd = 4 MSS;
  • 此时可以发送四个TCP最大报文段,成功接收后,cwnd = 8 MSS......

  由于TCP是一次性将窗口内的所有报文发出,所以所有报文都到达并被确认的时间,近似的等于一个RTT(记住这个结论,后面所述的RTT都是基于这个结论)。所以在这个阶段,拥塞窗口cwnd的长度将在每个RTT后翻倍,也就是发送速率将以指数级别增长(所以不要被慢启动这个名字误导了)。那这个过程什么时候改变呢,这又分几种情况:


  • 第一种:若在慢启动的过程中,发生了数据传输超时,则此时TCP将ssthresh的值设置为cwnd / 2,然后将cwnd重新设置为1MSS,重新开始慢启动过程,这个过程可以理解为试探上限;
  • 第二种:第一步试探出来的上限ssthresh将用在此处。若cwnd的值增加到>= ssthresh时,此时若继续使用慢启动的翻倍增长方式可能有些鲁莽,所以这个时候结束慢启动,改为拥塞避免模式;
  • 第三种:若发送方接收到了某个报文的三次冗余确认(即触发了快速重传的条件),则进入到快速恢复阶段;同时,ssthresh = cwnd / 2,毕竟发生快速重传也可以认为是发生拥塞导致的丢包,然后cwnd = ssthresh + 3MSS;

  以上就是慢启动的过程,下面来介绍拥塞避免。

 

 2.5 拥塞避免

  刚进入这个模式时,cwnd的大小近似的等于上次拥塞时的值的一半(这是由进入这个模式的条件决定的),也就是说当前的cwnd很接近产生拥塞的值。所以,拥塞避免是一个速率缓慢且线性增长的过程,在这个模式下,每经历一个RTT(请注意2.4中有关RTT的结论),cwnd的大小增加1MSS,也就是说,假设cwnd包含10个报文的大小,则每接收到一个确认报文,cwnd增加1/10 MSS。这个线性增长的过程什么时候结束,分为两种情况:


  • 第一种:在这个过程中,发生了超时,则表示网络拥塞,这时候,ssthresh 被修改为cwnd / 2,然后cwnd被置为1MSS,并进入慢启动阶段;
  • 第二种:若发送方接收到了某个报文的三次冗余确认(即触发了快速重传的条件),此时也认为发生了拥塞,则,ssthresh 被修改为 cwnd / 2,然后cwnd被置为ssthresh + 3MSS,并进入快速恢复模式;

  我们可以看到,慢启动和拥塞避免在接收到三个冗余的确认报文时,处理方式是一样的:判断发生了拥塞,并减小ssthresh 的大小,但是cwnd的大小却不见得有减小多少,这一点让人疑惑。我个人认为是这样,虽然发送方通过接收三次冗余确认报文,判断可能存在拥塞,但是既然可以收到冗余的确认报文,表示拥塞不会太严重,甚至已经不再拥塞,所以对cwnd的减小不是这么剧烈。

 

 2.6 快速恢复

  快速恢复和上面两种模式不太一样,这种模式在TCP规范中并没有强制要求实现,只是一种推荐实现的模式。在快速恢复阶段,每接收到一个冗余的确认报文,cwnd就增加1MSS,其余不变,而当发生以下两种情况时,将退出快速恢复模式:


  • 第一种:在快速恢复过程中,计时器超时,这时候,ssthresh 被修改为 cwnd / 2,然后cwnd被置为1MSS,并进入慢启动阶段;
  • 第二种:若发送方接收到一条新的确认报文(不是冗余确认),则cwnd被置为ssthresh,然后进入到拥塞避免模式;

  这里有一个疑问,进入到此模式的条件就是接收到三次冗余的确认报文,判断报文丢失,那为什么再次接收到冗余确认报文时,cwnd还是要增长呢?我搜遍网上博客,只在一篇博客中找到一种说法,我认为还是有一定道理的:此时再次收到一条冗余的确认报文,表示发送端发出的报文又有一条离开网络到达了接收端(虽然不是接收端当前想要的一条),这说明网络中腾出了一条报文的空间,所以允许发送端再向网络中发送一条报文。但是由于当前序号最小的报文丢失,导致拥塞窗口cwnd无法向前移动,于是只好将cwnd增加1MSS,于是发送端又可以发送一条数据段,提高了网络的利用率。

 

 2.7 三种模式相互转换状态图

  下面给出一张三种模式互相转换的状态图,途中箭头上的是转换的条件,条件有上下两部分,横线上方的是上面事件引起的转换,而下方是转换时发生的操作。

计算机网络之TCP协议流量拥塞控制算法原理:滑动窗口cwnd与rwnd

 

 

三、总结

  拥塞控制应该是TCP中相对比较复杂的一个部分了,理解起来不是那么容易。在写这篇博客之前,对于上面所说的三种模式,我只知道具体的流程,却有很多地方不清楚为什么要这么做。但是在写这篇博客时,反复阅读书本,找博客阅读的过程让我对慢慢理解了它们的意图。这就是我写博客的理由,通过复述,来加深自己的理解,同时也希望这篇博客对看到的人有所帮助。

 

四、参考


  • 《计算机网络——自顶向下方法(原书第七版)》
  • https://blog.csdn.net/jeason29/article/details/50427397/



推荐阅读
  • 深入理解KMP算法及其应用
    本文详细介绍了KMP算法的原理和实现方法,包括如何计算next数组以及如何利用next数组进行高效的字符串匹配。 ... [详细]
  • 本文详细介绍了如何配置Apache Flume与Spark Streaming,实现高效的数据传输。文中提供了两种集成方案,旨在帮助用户根据具体需求选择最合适的配置方法。 ... [详细]
  • 开发笔记:哈希的应用
    开发笔记:哈希的应用 ... [详细]
  • 一面问题:MySQLRedisKafka线程算法mysql知道哪些存储引擎,它们的区别mysql索引在什么情况下会失效mysql在项目中的优化场景&# ... [详细]
  • 深入理解HTTP及TCP基础知识
    本文详细解析了TCP的三次握手与四次挥手过程,探讨了HTTP与HTTPS的区别及其特性,并深入讲解了HTTP缓存机制以及GET与POST请求的主要差异。 ... [详细]
  • 深入理解任意分频技术及其在FPGA中的应用
    本文探讨了FPGA中任意分频的重要性,特别是其在高频精确控制中的应用。文章不仅介绍了传统的分频方法,还详细阐述了一种基于DDS(直接数字合成)相位累加器的高精度任意分频技术,旨在为工程师和爱好者提供一种新的思路。 ... [详细]
  • 基于花生壳域名的Android与ESP8266远程控制系统搭建
    本文介绍了一种使用Android设备、ESP8266模块及路由器,结合花生壳动态域名解析服务实现远程控制的方法。通过该方法,用户能够有效解决因公网IP变动导致的连接问题,实现稳定可靠的远程控制。 ... [详细]
  • 本文探讨了Unix和Linux操作系统的起源和发展历程。从20世纪60年代计算机技术的初期阶段,到Unix的诞生及后续Linux的崛起,文章详细介绍了这些操作系统如何逐步成为现代计算不可或缺的一部分。 ... [详细]
  • 本文详细介绍了基于模型相似性的聚类采样算法的实现过程,并探讨了该算法在面对样本量和梯度攻击时的表现。通过具体的实验结果,分析了算法的鲁棒性和潜在的安全威胁。 ... [详细]
  • 算法技能是求职大厂不可或缺的一部分,本文将通过LeetCode上的经典问题“加一”来提升你的算法思维与实践能力。 ... [详细]
  • Java程序设计第五周学习总结与实践
    本次学习总结涵盖了本周在Java程序设计课程中的学习要点,包括代码阅读、抽象类的应用、接口的使用以及面向接口编程的概念。同时,还包括了具体的书面作业解析。 ... [详细]
  • 微型计算机主机的关键组件解析
    本文详细探讨了微型计算机主机的核心组成部分,包括微处理器、内存储器、输入输出接口等,并解释了这些部件如何协同工作以构建一个完整的微型计算机系统。 ... [详细]
  • 本文深入探讨了Redis中的两种主要持久化方式——RDB(Redis Database)和AOF(Append Only File),并详细解析了两者的实现机制、优缺点以及在实际应用中的选择策略。 ... [详细]
  • 计算机网络SPoC作业指导
    本指导旨在帮助学生理解和完成计算机网络课程中的SPoC作业。提供解题思路和方法,强调独立思考的重要性,避免直接抄袭。 ... [详细]
  • ArchSummit深圳2014将于7月18日拉开帷幕,所有讲师已确认,涵盖9个热门话题,共36场精彩报告。InfoQ中文站提供了详细的讲师和报告列表。 ... [详细]
author-avatar
li-yuefang_883
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有