一、Cork算法概述

Cork算法与Nagle算法类似,也有人把Cork算法称呼为super-Nagle。Nagle算法提出的背景是网络因为大量小包小包而导致利用率低下产生网络拥塞,网络发生拥塞的时候性能还会进一步下降,因此Nagle算法通过ACK确认包来触发新数据包的发送(ACK确认包意味着对端已经接收到了一个数据包,即有一个数据包已经离开中间网络,此时可以在向中间网络注入一个数据包块,这称呼为self-clocking)。Cork算法则更为激进,一旦打开Cork算法,TCP不关注是否有收到ACK报文,只要当前缓存中累积的数据量不足以组成一个full-sized数据包就不会将数据包发出,直到一个RTO超时后才会把不满足一个full-sized的数据包发出去(实际上是通过一个persist timer来设置的这个RTO定时时间,persist timer超时的时候就会强制发送)。

linux中可以通过TCP_CORK选项来设置socket打开Cork算法。TCP_NODELAY选项和TCP_CORK选项在linux早期版本是互斥的,但目前最新的linux版本已经可以同时打开这两个选项了,但是TCP_CORK选项的优先级要比TCP_NODELAY选项的优先级要高。

二、wireshark示例

下面我们看几个wireshark的示例对进一步理解cork算法,同时要注意和前面Nagle的示例对比。下面的示例中同样设置client侧通过SYN包通告MSS为(50+12)bytes,server端扣除12bytes的TSopt选项后(包含两个nop选项),最大只能发送50bytes的数据包了。

1、Cork算法打开,Nagle算法默认打开

如下图所示,client与serve端建立TCP连接后,server端立即写入8bytes的数据,接着休眠5s然后写入105bytes的数据。

server端写入的8bytes数据在No4报文中发送,但是可以看到No3并没有在No3后立即发送,原因就是此时Cork算法处于打开状态,此时累计缓存不满足一个mss,因此不会立即发送,但是server端会在write写入数据的时候启动一个定时器,定时器定时时间为RTO,从server端程序中可以获取到当前RTO为2.104s,可以看到No3和No4之间的时间差差不多就是2.104s。最终这个定时器超时,发出了No4数据包。接着写入的105bytes数据,因此前100byte可以组成两个full-sized的数据包,因此会立即发出,对应No6和No7数据包。最后的5bytes数据直到No10采发出。同样server端在接收到No9的ACK报文的时候,发现当前没有已经发出去的还没被ACK数据,而缓存中还有数据因为窗口限制或者Cork限制等原因没有发出去,那么同样会启动刚刚那个定时器,超时时间为RTO,此时从server端程序中可以获取当前的RTO为1.968s,可以看到这个时间间隔与No9和No10之间的时间间隔基本相同。

2、Cork算法关闭,Nagle算法默认打开

关闭Cork算法,重新运行示例1的测试程序,结果如下,不再赘述,请自行与上面的wireshark截图对比

3、Cork算法与Nagle算法交互

上面我们说过TCP_CORK选项的优先级要比TCP_NODELAY选项的优先级要高(注意TCP_NODELAY是关闭Nagle算法),下面我们来看一个示例。

  • 如下图所示,server端建立连接后,先设置TCP_CORK选项打开,然后应用层连续写入两次,每次写入8bytes,可以从下图中看到server端写入的数据受限于Cork算法并没有立即发出。

  • 接着休眠200ms后,在打开TCP_NODELAY选项后,可以看到No4处的报文立即发出了(No4和No3正好大约相差200ms),原因是虽然TCP_NODELAY选项的优先级比TCP_CORK优先级低,但是这个只对设置TCP_NODELAY后的应用层写入生效,在开始设置TCP_NODELAY选项的时候会尝试忽略Cork算法而将缓存中的数据全部发出。

  • 打开TCP_NODELAY后,server端应用层立即写入两次,每次写入8bytes的数据。可以看到虽然打开了TCP_NODELAY,但是这两次写入并没有立即以两个数据包发出。

  • 接着server休眠200ms后写入50bytes的数据,此时已经可以组成一个full-sized数据包了,满足Cork算法发包条件,可以看到server端立即发出了No6数据包。可以看到No6和No4大约间隔200ms。

  • server端在收到No7的数据包后,发现当前没有已经发出的还没被ACK确认的数据包,但是缓存中还有因为Cork算法而不能发出的数据包,因此设置persist timer定时器,定时时间为RTO,从server端程序可以获取此时的RTO为2.016s。

  • 定时器超时后,最后的16bytes数据包忽略Cork算法的限制被server端强制发出,对应No8数据包。可以看到No8数据包与No7数据包大约相隔2.019s,与之前的定时器定时时间基本相符。

补充资料:

1、http://stackoverflow.com/questions/22124098/is-there-any-significant-difference-between-tcp-cork-and-tcp-nodelay-in-this-use

2、http://ccr.sigcomm.org/archive/2001/jan01/ccr-200101-mogul.pdf

TCP系列30—窗口管理&流控—4、Cork算法的更多相关文章

  1. TCP系列27—窗口管理&流控—1、概述

    在前面的内容中我们依次介绍了TCP的连接建立和终止过程和TCP的各种重传方式.接着我们在这部分首先关注交互式应用TCP连接相关内容如延迟ACK.Nagle算法.Cork算法等,接着我们引入流控机制(f ...

  2. TCP系列31—窗口管理&流控—5、TCP流控与滑窗

    一.TCP流控 之前我们介绍过TCP是基于窗口的流量控制,在TCP的发送端会维持一个发送窗口,我们假设发送窗口的大小为N比特,网络环回时延为RTT,那么在网络状况良好没有发生拥塞的情况下,发送端每个R ...

  3. TCP系列32—窗口管理&流控—6、TCP zero windows和persist timer

    一.简介 我们之前介绍过,TCP报文中的window size表示发出这个报文的一端准备多少bytes的数据,当TCP的一端一直接收数据,但是应用层没有及时读取的话,数据一直在TCP模块中缓存,最终受 ...

  4. TCP系列36—窗口管理&流控—10、linux下的异常报文系列接收

    在这篇文章中我们看一下server端在接收到异常数据系列时的处理,主要目的是通过wireshark示例对这些异常数据系列的处理有一个直观的认识,感兴趣的自行阅读相关代码和协议,这里不再进行详细介绍 在 ...

  5. TCP系列35—窗口管理&流控—9、紧急机制

    一.概述 我们在最开始介绍TCP头结构的时候,里面有个URG的标志位,还有一个Urgent Pointer的16bits字段.当URG标志位有效的时候,Urgent Poinert用来指示紧急数据的相 ...

  6. TCP系列33—窗口管理&流控—7、Silly Window Syndrome(SWS)

    一.SWS介绍 前面我们已经通过示例看到如果接收端的应用层一直没有读取数据,那么window size就会慢慢变小最终可能变为0,此时我们假设一种场景,如果应用层读取少量数据(比如十几bytes),接 ...

  7. TCP系列34—窗口管理&流控—8、缓存自动调整

    一.概述 我们之前介绍过一种具有大的带宽时延乘积(band-delay product.BDP)的网络,这种网络称为长肥网络(LongFatNetwork,即LFN).我们想象一种简单的场景,假设发送 ...

  8. TCP系列29—窗口管理&流控—3、Nagle算法

    一.Nagle算法概述 之前我们介绍过,有一些交互式应用会传递大量的小包(称呼为tinygrams),这些小包的负载可能只有几个bytes,但是TCP和IP的基本头就有40bytes,如果大量传递这种 ...

  9. TCP系列28—窗口管理&流控—2、延迟ACK(Delayed Acknowledgments)

    一.简介 之前的内容中我们多次提到延迟ACK(Delayed Ack),延迟ACK是在RFC1122协议中定义的,协议指出,一个TCP实现应该实现延迟ACK,但是ACK不能被过度延迟,协议给出延迟AC ...

随机推荐

  1. Hive操作之向分区表中导入数据的语义错误

    1.建完分区表之后,向表中导入数据 命令为: load data local inpath '/home/admin/Desktop/2015082818' into table db_web_dat ...

  2. C Mingw gcc printf 刷新缓冲行

    C Mingw gcc printf 刷新缓冲行 参考:https://stackoverflow.com/questions/13035075/printf-not-printing-on-cons ...

  3. 第五节 Go数据结构之队列

    一.什么是队列 数据结构里的队列就是模仿现实中的排队.如上图中狗狗排队上厕所,新来的狗狗排到队伍最后,最前面的狗狗撒完尿走开,后面的跟上.可以看出队列有两个特点: (1) 新来的都排在队尾: (2) ...

  4. 北京Uber优步司机奖励政策(10月26日~11月1日)

    用户组:优步北京人民优步A组(适用于10月26日-11月1日) 滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/ ...

  5. 成都Uber优步司机奖励政策(3月4日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  6. 青岛Uber优步司机奖励政策(8/10-8/16)

    亲爱的Uber青岛优步的大司机朋友们,又到了每周发布奖励细则的时刻啦!下一周的奖励与上周有所不同,请一定要仔细按照自己的情况阅读!另外,之前参与过投票并表示想加入新小时保底政策的老司机朋友们从本周起, ...

  7. 4567: [Scoi2016]背单词

    4567: [Scoi2016]背单词 https://www.lydsy.com/JudgeOnline/problem.php?id=4567 题意: 题意看了好久,最后在其他人的博客里看懂了的. ...

  8. Entity Framework Core 导航属性 加载数据

    Loading Related Data https://docs.microsoft.com/en-us/ef/core/querying/related-data Eager loading me ...

  9. Machine Learning Basic Knowledge

    常用的数据挖掘&机器学习知识(点) Basis(基础): MSE(MeanSquare Error 均方误差),LMS(Least MeanSquare 最小均方),LSM(Least Squ ...

  10. Jmeter做压力测试的心得

    什么是性能压测? 也是最近刚刚接触到,就是被测试的系统,在一定的访问压力下,看程序运行是否稳定/服务器运行是否稳定,通常情况,是模拟多个请求同时 请求服务器,也就是在某个时间内,比如说1秒内,调用接口 ...