posts - 297,  comments - 15,  trackbacks - 0
1. 前言
 
TCP是具备流控和可靠连接能力的协议,为防止TCP发生拥塞或为提高传输效率,在网
络发展早期就提出了一些相关的TCP流控和优化算法,而且也被RFC2581规定是每个
TCP实现时要实现的。
 
本文中,为求方便把将“TCP分组段(segment)”都直接称为“包”。
 
2. 慢启动(slow start)和拥塞避免(Congestion Avoidance)
 
慢启动和拥塞避免是属于TCP发送方必须(MUST)要实现的,防止TCP发送方向网络传入大量的突发数据造成网络阻塞。

先介绍几个相关参数,是在通信双方中需要考虑但不在TCP包中体现的一些参数:

拥塞窗口(congestion window,cwnd),是指发送方在接收到对方的ACK确认前向允许网络发送的数据量,数据发送后,拥塞窗口缩小;接收到对方的ACK后,拥塞窗口相应增加,拥塞窗口越大,可发送的数据量越大。拥塞窗口初始值的RFC2581中被规定为不超过发送方MSS的两倍,而且不能超过两个TCP包,在RFC3390中更新了初始窗口大小的设置方法。

通告窗口(advertised window,rwnd),是指接收方所能接收的没来得及发ACK确认的数据量,接收方数据接收后,通告窗口缩小;发送ACK后,通告窗口相应扩大。

慢启动阈值(slow start threshold, ssthresh),用来判断是否要使用慢启动或拥塞避免算法来控制流量的一个参数,也是随通信过程不断变化的。

当cwnd < ssthresh时,拥塞窗口值已经比较小了,表示未经确认的数据量增大,需要启动慢启动算法;当cwnd > ssthresh时,可发送数据量大,需要启动拥塞避免算法。

拥塞窗口cwnd是根据发送的数据量自动减小的,但扩大就需要根据对方的接收情况进行扩大,慢启动和拥塞避免算法都是描述如何扩大该值的。

在启动慢启动算法时,TCP发送方接收到对方的ACK后拥塞窗口最多每次增加一个发送方MSS字节的数值,当拥塞窗口超过sshresh后或观察到拥塞才停止算法。

启动拥塞避免算法时,拥塞窗口在一个连接往返时间RTT内增加一个最大TCP包长度的量,一般实现时用以下公式计算:
      cwnd += max(SMSS*SMSS/cwnd, 1)            (2.1)
SMSS为发送方MSS。

TCP发送方检测到数据包丢失时,需要调整ssthresh,一般按下面公式计算:
      ssthresh = max (FlightSize / 2, 2*SMSS)    (2.2)
其中FlightSize表示已经发送但还没有被确认的数据量。
 
3. 快速重传(fast retransmit)和快速恢复(fast recovery)

TCP接收方收到错序的TCP包时要发送复制的ACK包回应,提示发送方可能出现网络丢包;发送方
收到连续3个重复的ACK包后启动快速重传算法,根据确认号快速重传那个可能丢失的包而不必等
重传定时器超时后再重传,普通的重传是要等到重传定时器超时还没收到ACK才进行的。这个算
法是TCP发送方应该(SHOULD)实现的,不是必须。TCP发送方进行了快速重传后进入快速恢复阶段
,直到没再接收重复的ACK包。

快速重传和快速恢复具体过程为:
1. 当收到第3个重复的ACK包时,ssthreh值按公式2.2重新设置;
2. 重传丢失的包后,将拥塞窗口cwnd设置为sshresh+3*SMSS,人工扩大了拥塞窗口;
3. 对于每个接收到的重复的ACK包,cwnd相应增加SMSS,扩大拥塞窗口;
4. 如果新的拥塞窗口cwnd值和接收方的通告窗口值允许的话,可以继续发新包;
5. 当收到下一个ACK确认了新数据时,将cwnd大小调整为sshresh,减少窗口;对接收方
   来说,接收到重发的TCP包后就要发此ACK确认当前接收的数据。
 
4. 结论
这些算法重点在于保持网络的可靠性和可用性,防止网络阻塞造成的网络崩溃,是相对
比较保守的。

5. 附录讨论

A君: 这些算法都是针对通信双方的事, 但如果从开发防火墙等中间设备的角度来看,
     中间设备有必要考虑这些么?
端木: 这个...我好象也看不出必要性,因为算法的参数都是在双方内部而不在TCP数据包
      中体现...但应该会让中间设备轻松点,这个就象在马路开车,这些算法就是交规
      让你开得规矩点,交警只关心你开车的情况,而不管你开的是什么车,开得好交警
      也轻松。好车可以让你很容易开好,但差车也可以开好。

A君: 这些算法原型提出也很早了, 最早是88年的事, 当时网络都处于初级阶段, 有个
     9600bps的猫就很牛了, 计算机性能也很差, 因此实施这些算法还有点用; 但现
     在过了快20年了, 百兆都快淘汰, 千兆, 万兆网络都快普及了, 即使PC机的内存
     也都上G了,再规矩这种几K级别的数据量有意思么? 就好象现在喷气式战斗机都到
     第4代了, 再研究螺旋桨战斗机还有意思么?
端木: 这个...这个就象病毒库了, 里面不也有无数的DOS时代的病毒, 你以后这辈子估计
      都见不着的,但没有哪个防病毒厂商会把这些病毒从库中剔除,库是只增不减的。
      有这么个东西也是一样,正因为平时没用,谁也不注意,知道了就可以吹一吹,
      尤其拿去唬唬人是很有效的!

A君: 你真无聊!
端木: You got it! 不无聊干吗写博客啊!

端木: 搞技术有时候是很悲哀的一件事,必须牵扯七大姑八大姨的很多老东西,也就是向下
      兼容,到一定程度将成为进一步发展的最大障碍,讲一个从smth看到的不是笑话
      的笑话:

    现代铁路的铁轨间距是4英尺8点5英寸,铁轨间距采用了电车轮距的标准,而电车轮距
的标准则沿袭了马车的轮距标准。
    马车的轮距为何是4英尺8点5英寸?原来,英国的马路辙迹的宽度是4英尺8点5英寸。
如果马车改用其他尺寸的轮距,轮子很快就会在英国的老马路上撞坏。
    英国马路的辙迹宽度又从何而来?这可以上溯到古罗马时期。整个欧洲(包括英国)的老路都是罗马人为其军队铺设的,4英尺8点5英寸正是罗马战车的宽度。
    罗马战车的宽度又是怎么来的?答案很简单,它是牵引一辆战车的两匹马的屁股的总宽度。
    段子到这里还没有结束。美国航天飞机的火箭助推器也摆脱不了马屁股的纠缠———火箭助推器造好之后要经过铁路运送,而铁路上必然有一些隧道,隧道的宽度又是根据铁轨的宽度而来。代表着尖端科技的火箭助推器的宽度,竟然被两匹马的屁股的总宽度决定了。
转自:
http://www.cppblog.com/prayer/archive/2009/04/20/80527.html
posted on 2010-01-08 23:34 chatler 阅读(545) 评论(0)  编辑 收藏 引用 所属分类: Network

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年9月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用链接

留言簿(10)

随笔分类(307)

随笔档案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感觉这个博客还是不错,虽然做的东西和我不大相关,觉得看看还是有好处的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新评论

阅读排行榜

评论排行榜