协议森林10 魔鬼细节 (TCP滑窗管理)

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

TCP协议与"流"通信中,我们建立了滑窗(sliding window)的基本概念。通过滑窗与ACK的配合,我们一方面实现了TCP传输的可靠性,另一方面也一定程度上提高了效率。其工作方式如下面的视频所示:

如果视频加载有问题,可点下面链接: http://v.youku.com/v_show/id_XNDg1NDUyMDUy.html

然而,之前的解释只是概念性的。TCP为了达到更好的传输效率,对上面的工作方式进行了许多改进。The devil is in the details. 我们需要深入到细节,才能看清楚TCP协议的智慧所在。

累计ACK

TCP连接中,我们通过将ACK回复“附着”在其他数据片段的方式,减少了ACK回复所消耗的流量。但这并不是全部的故事。TCP协议并不是对每个片段都发送ACK回复。TCP协议实际采用的是累计ACK回复(accumulative acknowledgement)。接收方往往利用一个ACK回复来知会连续多个片段的成功接收。通过累计ACK,所需要的ACK回复通常可以降到50%。

如下图所示,橙色为已经接收的片段。方框为滑窗,滑窗可容纳3个片段。

累计ACK

滑窗还没接收到片段7时,已接收到片段8,9。这样就在滑窗中制造了一个“空穴”(hole)。当滑窗最终接收到片段7时,滑窗送出一个回复号为10的ACK回复。发送方收到该回复,会意识到,片段10之前的片段已经按照次序被成功接收。整个过程中节约了片段7和片段8所需的两个ACK回复。

此外,接收方在接收到片断,并应该回复ACK的时候,会故意延迟一些时间。如果在延迟的时间里,有后续的片段到达,就可以利用累计ACK来一起回复了。

滑窗结构

在之前的讨论中,我们以片段为单位,来衡量滑窗的大小的。真实的滑窗是以byte为单位表示大小,但这并不会对我们之前的讨论造成太大的影响。

发送方滑窗可以分为下面两个部分。offered window为整个滑窗的大小。

接收方滑窗可分为三个部分:

可以看到,接收方的滑窗相对于发送方的滑窗多了一个"Received; ACKed; Not Sent to Proc"的部分。接收方接收到的文本流必须等待进程来读取。如果进程正忙于做别的事情,那么这些文本流即使已经正确接收,还是需要暂时占用接收缓存。当出现上述占用时,滑窗的可用部分(也就是图中advertised window)就会缩水。这意味着接收方的处理能力下降。如果这个时候发送方依然按照之前的速率发送数据给接收方,接收方将无力接收这些数据。

流量控制

TCP协议会根据情况自动改变滑窗大小,以实现流量控制。流量控制(flow control)是指接收方将advertised window的大小通知给发送方,从而指导发送方修改offered window的大小。接收方将该信息放在TCP头部的window size区域:

发送方在收到window size的通知时,会调整自己滑窗的大小,让offered window和advertised window相符。这样,发送窗口变小,文本流发送速率降低,从而减少了接收方的负担。

零窗口

advertised window大小有可能变为0,这意味着接收方的接收能力降为0。发送方收到大小为0的advertised window通知时,停止发送。

当接收方经过处理,再次产生可用的advertised window时,接收方会通过纯粹的ACK回复来通知发送方,让发送方恢复发送。然而,ACK回复的传送并不是可靠的。如果该ACK回复丢失,那么TCP传输将陷入死锁(deadlock)状态。

为此,发送方会在零窗口后,不断探测接收方的窗口。窗口探测(window probe)时,发送方会向接收方发送包含1 byte文本流的TCP片段,并等待ACK回复(该ACK回复包含有window size)。由于有1 byte的数据存在,所以该传输是可靠的,而不用担心ACK回复丢失的问题。如果探测结果显示窗口依然为0,发送方会等待更长的时间,然后再次进行窗口探测,直到TCP传输恢复。

白痴窗口综合症

滑窗机制有可能犯病,比如白痴窗口综合症 (Silly Window Syndrome)。假设这样一种情形:接收方宣布(advertise)一个小的窗口,发送方根据advertised window,发送一个小的片段。接收方的小窗口被填满,经过处理,接收方再宣布一个小的窗口…… 这就是“白痴窗口综合症”:TCP通信的片段中包含的数据量很小。在这样的情况下,TCP通信的片段所含的信息都很小,网络流量主要是TCP片段的头部,从而造成流量的浪费 (由于TCP头部很大,我们希望每个TCP片段中含有比较多的数据)。

如果发送方不断发送小的片段,也会造成“白痴窗口”。为了解决这个问题,需要从两方面入手。TCP中有相关的规定,要求:

1. 接收方宣告的窗口必须达到一定的尺寸,否则等待。

2. 除了一些特殊情况,发送方发送的片段必须达到一定的尺寸,否则等待。特殊情况主要是指需要最小化延迟的TCP应用(比如命令行互动)。

总结

累计ACK减少了TCP传输过程中所需的ACK流量。通过流量管理,TCP连接两端的工作能力可以匹配,从而减少不不要的传输浪费。累计ACK和流量控制都是TCP协议的重要特征。

TCP协议相当复杂,并充斥着各种细节。然而TCP协议又是如此重要的一个协议,引领风骚三十年,可以说是互联网的奇迹。这些细节正是TCP协议成功的原因,并值得我们深入了解。

(转)协议森林10 魔鬼细节 (TCP滑窗管理)的更多相关文章

  1. (转)协议森林08 不放弃 (TCP协议与流通信)

    协议森林08 不放弃 (TCP协议与流通信) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! TCP(Transportation ...

  2. 协议森林08 不放弃 (TCP协议与流通信)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! TCP(Transportation Control Protocol)协议与IP ...

  3. (转)协议森林12 天下为公 (TCP堵塞控制)

    协议森林12 天下为公 (TCP堵塞控制) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在TCP协议中,我们使用连接记录TCP ...

  4. 协议森林09 爱的传声筒 (TCP连接)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在TCP协议与"流"通信中,我们概念性的讲解了TCP通信的方式 ...

  5. (转)协议森林09 爱的传声筒 (TCP连接)

    协议森林09 爱的传声筒 (TCP连接) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在TCP协议与"流" ...

  6. (转)协议森林11 涅槃 (TCP重新发送)

    协议森林11 涅槃 (TCP重新发送) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! TCP协议是一个可靠的协议.它通过重新发送 ...

  7. 协议森林03 IP接力赛 (IP, ARP, RIP和BGP协议)

    网络层(network layer)是实现互联网的最重要的一层.正是在网络层面上,各个局域网根据IP协议相互连接,最终构成覆盖全球的Internet.更高层的协议,无论是TCP还是UDP,必须通过网络 ...

  8. 协议森林02 小喇叭开始广播 (以太网与WiFi协议)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载. “小喇叭开始广播啦”,如果你知道这个,你一定是老一辈的人.“小喇叭”是五十年代到八十年代的儿童广播 ...

  9. 学过 C++ 的你,不得不知的这 10 条细节!

    每日一句英语学习,每天进步一点点: “Action may not always bring happiness; but there is no happiness without action.” ...

随机推荐

  1. LeetCode Day 6

    LeetCode0006 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" ,指定行数为 3 时,排 ...

  2. Android开发之《RXJava的简单实现》

    import android.util.Log; import rx.Observable; import rx.Subscriber; import rx.functions.Action1; pu ...

  3. CAD卸载/完美解决安装失败/如何彻底卸载清除干净cad各种残留注册表和文件的方法

    在卸载cad重装CAD时发现安装失败,提示是已安装或安装失败.这是因为上一次卸载后没有清理干净,系统会误认为已经安装过了.有的同学是新装的系统也会出现安装失败的情况,这是因为C++ 或者.NET的原因 ...

  4. php--0与空的判断

    使用empty()函数判断,两者都是true $a=0; if(trim($a)=="") { echo '数字0'; }

  5. [转]<版本二>写代码的小女孩

    天冷极了,下着雪,又快黑了.这是一年的最后一天——大年夜.在这又冷又黑的晚上,一个乖巧的小女孩在机房里调试程序.她从家里出来的时候还穿着一件外套,但是有什么用呢?那是一双很大的外套——那么大,不知是哪 ...

  6. 吴裕雄--天生自然 HADOOP大数据分布式处理:修改CenterOS 7系统时间为北京时间

  7. javaSE复习之——线程

    线程其实就是程序执行的一条路径,一个进程中可以包含多条线程,多线程并发执行可以提高程序效率,可以同使完成多项任务 多线程的应用场景 迅雷多线程一起下载 服务器同时处理多个客户请求 多线程原理(单核CP ...

  8. oppo互联网招聘-各类软件测试

    一.服务端测试专家 关键词:安全测试.白盒测试.性能测试.自动化.持续集成.服务端 岗位职责: 主导多个高日活产品的测试方案: 试点和推广自动化和持续集成: 改善测试相关流程和规范. 职位要求: 计算 ...

  9. Java8-19-lambda 重构代码

    通过本书的前七章,我们了解了Lambda和Stream API的强大威力. 你可能主要在新项目的代码中使用这些特性.如果你创建的是全新的Java项目,这是极好的时机,你可以轻装上阵,迅速地将新特性应用 ...

  10. iOS开发黑科技之runtime

    iOS 开发之黑科技-runtime runtime其实就是oc底层的一套C语音的API 调用方法的本质就是发消息, 1.动态交换两个方法的实现(特别是交换系统自动的方法) 2.动态添加对象的成员变量 ...