TCP Nagle算法简述
Nagle算法的基本定义是任意时刻,最多只能有一个未被确认的小段。所谓“小段”,指的是小于MSS尺寸的数据块,所谓“未被确认”,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到。
Nagle算法的规则(可参考tcp_output.c文件里tcp_nagle_check函数注释):
(1)如果包长度达到MSS,则允许发送;
(2)如果该包含有FIN,则允许发送;
(3)设置了TCP_NODELAY选项,则允许发送;
(4)未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;
(5)上述条件都未满足,但发生了超时(一般为200ms),则立即发送。
Nagle算法只允许一个未被ACK的包存在于网络,它并不管包的大小,因此它事实上就是一个扩展的停-等协议(停止等待ARQ协议),只不过它是基于包停-等的,而不是基于字节停-等的。Nagle算法完全由TCP协议的ACK机制决定,这会带来一些问题,比如如果对端ACK回复很快的话,Nagle事实上不会拼接太多的数据包,虽然避免了网络拥塞,网络总体的利用率依然很低。
Nagle算法的应用场景
在Nagle算法的Wiki主页,有这么一段话:
In general, since Nagle's algorithm is only a defense against careless applications, it will not benefit a carefully written application that takes proper care of buffering; the algorithm has either no effect, or negative effect on the application.
可见编程模型对“减少网络上小包数量”的影响,言外之意,Nagle算法是个有针对性的优化-针对交互式应用,不是放之四海而皆准的标准,要想有一个比较好的方案,别指望它了,还是应用程序自己搞定才是正解!要想Nagle算法真的能够减少网络上小包数量而又不引入明显延迟,对TCP数据的产生方式是有要求的,交互式应用是其初始针对的对象,,Nagle算法要求数据必须是“乒乓型”的,也就是说,数据流有明确的边界且一来一回,类似人机交互的那种,比如telnet这种远程终端登录程序,数据是人从键盘敲入的,边界基本上就是击键,一来一回就是输入回显和处理回显。Nagle算法在上面的场景中保证了下一个小包发送之前,所有发出的包已经得到了确认,再次我们看到,Nagle算法并没有阻止发送小包,它只是阻止了发送大量的小包。
换句话说,所谓的“乒乓型”模式就是“write-read-write-read”模式-人机交互模式,但是对于Wiki中指出的“write-write-read”(很多的request/response模式C/S服务就是这样的,比如HTTP)-程序交互模式,Nagle算法和延迟ACK(延迟确认机制)拔河的恶果就会被放大。
有一篇很好的文章http://baus.net/on-tcp_cork/《TCP_CORK: More than you ever wanted to know》,文章说,Nagle算法对于数据来自于user input的那种应用是有效的,但是对于数据generated by applications using stream oriented protocols,Nagle算法纯粹引入了延迟,这个观点我非常赞同,因为对于人而言,TCP登录俄远程计算机就是一个处理机,人希望自己的操作马上展示结果,其模式就是write-read-write-read的,但是对于程序而言,其数据产生逻辑就不像人机交互那么固定,因此你就不能假定程序依照任何序列进行网络IO,而Nagle算法是和数据IO的序列相关的。实际上就算接收端没有启用延迟ACK,Nagle算法应用于write-write-read序列也是有问题的,作者的意思是,平白无故地引入了额外的延迟。
难道真的有这么复杂吗?作者没有提出如何靠编程把问题解决,但是Nagle算法的Wiki页面上提到了”尽量编写好的代码而不要依赖TCP内置的所谓的算法“来优化TCP的行为。
TCP_NODELAY 套接字选项
默认情况下,发送数据采用Negle 算法。这样虽然提高了网络吞吐量,但是实时性却降低了,在一些交互性很强的应用程序来说是不允许的,
使用TCP_NODELAY选项可以禁止Negale 算法。
延迟确认机制(TCP delayed acknowledgment)
wiki的解释https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment
1989 RFC 1122定义,全名Delayed Acknowledgment,简称延迟ACK,翻译为延迟确认。
与Nagle算法一样,延迟ACK的目的也是为了减少网络中传输大量的小报文数,但该报文数是针对ACK报文的。
一个来自发送端的报文到达接收端,TCP会延迟ACK的发送,希望应用程序会对刚刚收到的数据进行应答,这样就可以用新数据将ACK捎带过去。
当Nagle算法遇到Delayed ACK
在一个有数据传输的TCP连接中,如果只有数据发送方启用Nagle算法,在其连续发送多个小报文时,Nagle算法机制会减少网络中的小报文数量。这就意味着,同样传输相同大小的应用数据,在网络上的报文个数却不同。
举个例子,发送端需要连续发送5个写操作(应用程序将数据写入到缓冲池的动作)的小报文,首先发送第一个,由于Nagle算法的作用,在未收到第一个报文确认前,发送端在等待写操作的同时进行读操作,接收端并未启用延迟确认(视TCP delay ACK时间为0),尽管刚收到该报文就发出确认,但由于网络延时的原因,在收集齐另外4个小报文后,发送方才收到了第一个报文的ACK,则后面的4个报文会一起发送出去(大小未超过MSS),接收端再次ACK。
在上述发送5个小报文的过程中,只用了4个报文就实现了。但如果发送端未启用Nagle算法,完成整个过程则至少需要8个报文或10个报文才能实现,这里接收端未启用延迟确认,如下图所示。启用Nagle算法和未启用Nagle算法的场景中,从完成数据发送的时间来看,未启用Nagle算法的方式花费的时间会更长一些,如下图所示。这里基本看到了Nagle算法的好处了。
还是上述数据传输场景,发送端未启用Nagle算法,但接收端延迟确认默认时间为200ms,来看看这时的情况。 RFC 1122规定,Delayed ACK对单个的小报文可以延长确认的时间,但不允许有两个连续的小报文不被确认。所以,当发送端连续发送两个报文后,接收端必须给予确认。这时的数据传输情况如下图,只有当第5个报文到达后,接收端由于延迟确认机制,会导致200ms的延时存在。
接下来看看,当Nagle算法遇到Delayed ACK时会是什么情况。按照常理推断,两种深思熟虑的功能设计,应该是1+1>2的效果。具体如何,还是请事实说话。
先继续看上面的假设场景,该场景要求发送端向接收端发送5个连续的写操作数据,但网络延时较大,同时发送端启用Nagle算法,接收端Delayed ACK默认为200ms。
发送方先发出一个小报文,接收端收到后,由于延迟确认的机制,等待发送方的下一个报文到达。而发送方由于Nagle算法机制,在未接收到第一个报文的确认前,不会发送已读取到的报文。 在这种场景下,暂不考虑应用处理时间,完成整个数据传输所需时间为2RTT+400ms,貌似情况不是特别糟糕。
如果上述其他条件不变,发送方应用写操作延时稍微变大,或发送端的应用操作延时稍大,我们再看看,完成这个操作的延时情况。
发送方先发出一个小报文,接收端收到后,由于延迟确认的机制,等待发送方的下一个报文到达。由于发送方应用数据写操作延时较大,在经过RTT+200ms后,读取到了下一个需要发送的内容,此时接收到了第一个报文的确认,而网络中未有没被确认的报文,发送方需要再将第二个小报文发送出去,以此类推,直到最后一个小报文被发送,且接收到该报文的确认,此时整个数据传输过程完成。
在这种情景下,完成整个数据传输所需时间则为5RTT+5*200ms,明显增大了不少。如果相同情境下,有成千上万的小报文发送,则整体使用时间相当可观了。
在实际情况下,如果发送方程序做了一系列的写、写、读操作的现象,这样的操作都会触发Nagle和延迟ACK算法之间的交互作用,应该尽量避免。
===========================END===========================
TCP Nagle算法简述相关推荐
- 【计算机网络】2、TCP:四次挥手与TIME_WAIT、shutdown() 优雅关闭 server、探活、拥塞窗口与 Nagle 算法、端口占用、tcp 的流式协议、可靠性
文章目录 六.四次挥手 与 TIME_WAIT 6.1 TIME_WAIT 的作用 6.2 TIME_WAIT 的危害和方案 七.server 用 shutdown() 优雅关闭 7.1 close( ...
- Nagle算法延时确认
数据流分类 成块数据 交互数据 Rlogin需要远程系统(服务器)回显我们(客户)键入的字符 数据字节和数据字节的回显都需要对方确认 rlogin 每次只发送一个字节到服务器,而Telnet 可以 ...
- 禁用 Nagle 算法
有没有发现一个很奇怪的组合,即 Nagle 算法和延时 ACK 的组合.这个组合为什么奇怪呢? 我举一个例子你来体会一下.比如,客户端分两次将一个请求发送出去,由于请求的第一部分的报文未被确认,Nag ...
- TCP/IP学习笔记(六)Nagle算法
在TCP传输数据流中,存在两种类型的TCP报文段,一种包含成块数据(通常是满长度的,携带一个报文段最多容纳的字节数),另一种则包含交互数据(通常只有携带几个字节数据). 对于成块数据的报文段,TCP采 ...
- TCP/IP之(四)Delay ack 和 Nagle算法
Delay ack(延迟确认) 正常情况下服务器收到一个请求时就会立即回复ACK确认给客户端,然后客户端再发送下一个包,服务器再进行回复.有时候服务器回复的ACK包有长度,但实际内容长度为0,这也没关 ...
- 在c语言中如何屏蔽一段程序,如何在用C语言关闭TCP程序中的Nagle算法
TCP为了防止在网络中过多的小分组会导致阻塞,因此提供了Nagle算法:要求一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组的确认到达之前不能发送其他的小分组.相反,TCP收集这些少量 ...
- 网络协议:TCP保活机制和Nagle算法
一 Nagle算法背景 有时候,我们可能会遇到一些很小的分组,比如,20字节的IP首部,20字节的TCP首部和1字节的数据,如果很多这样的小分组数据,在局域网一般不会出现拥塞,但是在广域网就可有可能. ...
- TCP之Nagle算法延迟ACK
1. Nagle算法: 是为了减少广域网的小分组数目,从而减小网络拥塞的出现: 该算法要求一个tcp连接上最多只能有一个未被确认的未完成的小分组,在该分组ack到达之前不能发送其他的小分组,tcp需要 ...
- 再次谈谈TCP的Nagle算法与TCP_CORK选项
事件回放 使用OpenVPN传输虚拟桌面流量,终端上有明显逐帧刷屏现象,网络环境为百兆局域网. 分析 1.首先将OpenVPN改为TCP模式,因为局域网环境下TCP和UDP差别不大,不会引起重传叠加问 ...
最新文章
- 聊聊Spring事务失效的12种场景,太坑人了
- 关于C++中数组下标越界不报错的问题
- C++知识点55——函数模板
- 怎么将织梦图集模型编辑器改为文章编辑器?
- 邮箱服务器ip地址白名单,申请SSL证书时如何设置IP地址白名单和邮箱白名单
- 对话框找不到WM_ERASEBKGND消息的解决方法与对话框背景图片的载入方法
- 前端学习(2309):react之同级传值
- 针对不同pandas版本进行列名的修改
- Jquery中用offset().top和offsetTop的比较
- tensorflow随笔——交叉熵公式推导
- 黑马程序员C++学习笔记(第二阶段核心:面向对象)(二)
- 21个非常实用的She脚本实例
- ukf实测信号的预测 matlab,无迹卡尔曼滤波UKF无线传感器网络定位跟踪matlab源码实现.pdf...
- matlab矩阵乘法不同行,矩阵乘法在numpy/matlab/数学上的不同
- 干货 | 团队建设共同愿景的探索
- 荣耀手机如何批量删除日历日程?日历日程提醒便签
- 《速度与激情》男主演保罗沃克车祸身亡,再见速度再见难续的激情
- 什么东西可以改善睡眠,可以试试这些助眠好物改善睡眠
- github Your account has been flagged.提示情况的解决办法
- P02014182王子恒信息论作业