Nagle 算法
1. Nagel算法
TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认。为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。(一个连接会设置MSS参数,因此,TCP/IP希望每次都能够以MSS尺寸的数据块来发送数据)。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的包存在于网络,它并不管包的大小,因此它事实上就是一个扩展的停-等协议,只不过它是基于包停-等的,而不是基于字节停-等的。Nagle算法完全由TCP协议的ACK机制决定,这会带来一些问题,比如如果对端ACK回复很快的话,Nagle事实上不会拼接太多的数据包,虽然避免了网络拥塞,网络总体的利用率依然很低。
Nagle算法是silly window syndrome(SWS)预防算法的一个半集。SWS算法预防发送少量的数据,Nagle算法是其在发送方的实现,而接收方要做的时不要通告缓冲空间的很小增长,不通知小窗口,除非缓冲区空间有显著的增长。这里显著的增长定义为完全大小的段(MSS)或增长到大于最大窗口的一半。
注意:BSD的实现是允许在空闲链接上发送大的写操作剩下的最后的小段,也就是说,当超过1个MSS数据发送时,内核先依次发送完n个MSS的数据包,然后再发送尾部的小数据包,其间不再延时等待。(假设网络不阻塞且接收窗口足够大)
举个例子,比如之前的blog中的实验,一开始client端调用socket的write操作将一个int型数据(称为A块)写入到网络中,由于此时连接是空闲的(也就是说还没有未被确认的小段),因此这个int型数据会被马上发送到server端,接着,client端又调用write操作写入‘\r\n’(简称B块),这个时候,A块的ACK没有返回,所以可以认为已经存在了一个未被确认的小段,所以B块没有立即被发送,一直等待A块的ACK收到(大概40ms之后),B块才被发送。整个过程如图所示:

这里还隐藏了一个问题,就是A块数据的ACK为什么40ms之后才收到?这是因为TCP/IP中不仅仅有nagle算法,还有一个TCP确认延迟机制 。当Server端收到数据之后,它并不会马上向client端发送ACK,而是会将ACK的发送延迟一段时间(假设为t),它希望在t时间内server端会向client端发送应答数据,这样ACK就能够和应答数据一起发送,就像是应答数据捎带着ACK过去。在我之前的时间中,t大概就是40ms。这就解释了为什么'\r\n'(B块)总是在A块之后40ms才发出。
当然,TCP确认延迟40ms并不是一直不变的,TCP连接的延迟确认时间一般初始化为最小值40ms,随后根据连接的重传超时时间(RTO)、上次收到数据包与本次接收数据包的时间间隔等参数进行不断调整。另外可以通过设置TCP_QUICKACK选项来取消确认延迟。
关于TCP确认延迟的详细介绍可参考:http://blog.csdn.net/turkeyzhou/article/details/6764389
2. TCP_NODELAY 选项
默认情况下,发送数据采用Negale 算法。这样虽然提高了网络吞吐量,但是实时性却降低了,在一些交互性很强的应用程序来说是不允许的,使用TCP_NODELAY选项可以禁止Negale 算法。
此时,应用程序向内核递交的每个数据包都会立即发送出去。需要注意的是,虽然禁止了Negale 算法,但网络的传输仍然受到TCP确认延迟机制的影响。
3. TCP_CORK 选项
所谓的CORK就是塞子的意思,形象地理解就是用CORK将连接塞住,使得数据先不发出去,等到拔去塞子后再发出去。设置该选项后,内核会尽力把小数据包拼接成一个大的数据包(一个MTU)再发送出去,当然若一定时间后(一般为200ms,该值尚待确认),内核仍然没有组合成一个MTU时也必须发送现有的数据(不可能让数据一直等待吧)。
然而,TCP_CORK的实现可能并不像你想象的那么完美,CORK并不会将连接完全塞住。内核其实并不知道应用层到底什么时候会发送第二批数据用于和第一批数据拼接以达到MTU的大小,因此内核会给出一个时间限制,在该时间内没有拼接成一个大包(努力接近MTU)的话,内核就会无条件发送。也就是说若应用层程序发送小包数据的间隔不够短时,TCP_CORK就没有一点作用,反而失去了数据的实时性(每个小包数据都会延时一定时间再发送)。
4. Nagle算法与CORK算法区别
Nagle算法和CORK算法非常类似,但是它们的着眼点不一样,Nagle算法主要避免网络因为太多的小包(协议头的比例非常之大)而拥塞,而CORK算法则是为了提高网络的利用率,使得总体上协议头占用的比例尽可能的小。如此看来这二者在避免发送小包上是一致的,在用户控制的层面上,Nagle算法完全不受用户socket的控制,你只能简单的设置TCP_NODELAY而禁用它,CORK算法同样也是通过设置或者清除TCP_CORK使能或者禁用之,然而Nagle算法关心的是网络拥塞问题,只要所有的ACK回来则发包,而CORK算法却可以关心内容,在前后数据包发送间隔很短的前提下(很重要,否则内核会帮你将分散的包发出),即使你是分散发送多个小数据包,你也可以通过使能CORK算法将这些内容拼接在一个包内,如果此时用Nagle算法的话,则可能做不到这一点。
Nagle 算法的更多相关文章
- TCP/IP之Nagle算法与40ms延迟
Nagle算法是针对网络上存在的微小分组可能会在广域网上造成拥塞而设计的.该算法要求一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组确认到达之前不能发送其他的小分组.同时,TCP收集这 ...
- socket.setNoDelay([noDelay]) 用的是Nagle算法
Nagle算法是以他的发明人John Nagle的名字命名的,它用于自动连接许多的小缓冲器消息:这一过程(称为nagling)通过减少必须发送包的个数来增加网络软件系统的效率.Nagle算法于1984 ...
- 延迟确认和Nagle算法
前篇文章介绍了三次握手和四次挥手,了解了TCP是如何建立和断开连接的,文末还提到了抓包挥手时的一个“异常”现象,当时无法解释,特地查了资料,知道了数据传输中的延迟确认策略. 何谓延迟确认策略? WIK ...
- Nagle算法
简介 Nagle算法是以他的发明人John Nagle的名字命名的,它用于自动连接许多的小缓冲器消息:这一过程(称为nagling)通过减少必须发送包的个数来增加网络软件系统的效率.Nagle算法于1 ...
- UNIX网络编程——TCP—经受时延与nagle算法、滑动窗口、拥塞窗口
1.经受时延: TCP在接收到数据时并不立即发送ACK,相反,它推迟发送,以便将ACK与需要沿该方向发送的数据一起发送,时延为200ms,超过时延范围,发送确认. 2.nagle算法: 一个TCP连接 ...
- TCP Nagle算法&&延迟确认机制
TCP Nagle算法&&延迟确认机制 收藏 秋风醉了 发表于 3年前 阅读 1367 收藏 0 点赞 0 评论 0 [腾讯云]买域名送云解析+SSL证书+建站!>>> ...
- TCP粘包, UDP丢包, nagle算法
一.TCP粘包 1. 什么时候考虑粘包 如果利用tcp每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题(因为只有一种包结构,类似于http协议,UDP不会出 ...
- TCP-IP详解:Nagle算法
在使用一些协议通讯的时候,比如Telnet,会有一个字节字节的发送的情景,每次发送一个字节的有用数据,就会产生41个字节长的分组,20个字节的IP Header 和 20个字节的TCP Header, ...
- 粘包、拆包发生原因滑动窗口、MSS/MTU限制、Nagle算法
[TCP协议](3)---TCP粘包黏包 [TCP协议](3)---TCP粘包黏包 有关TCP协议之前写过两篇博客: 1.[TCP协议](1)---TCP协议详解 2.[TCP协议](2)---TCP ...
随机推荐
- [Swift]LeetCode944. 删除列以使之有序 | Delete Columns to Make Sorted
We are given an array A of N lowercase letter strings, all of the same length. Now, we may choose an ...
- 工作随笔—Java容器基础知识分享(持有对象)
1. 概述 通常,程序总是运行时才知道的根据某些条件去创建新对象.在此之前,不会知道所需对象的数量,甚至不知道确切的类型,为解决这个普遍的编程问题:需要在任意时刻和任意位置创建任意数量的对象,所以,就 ...
- HBase之Table.put客户端流程(续)
上篇博文中已经谈到,有两个流程没有讲到.一个是MetaTableAccessor.getRegionLocations,另外一个是ConnectionImplementation.cacheLocat ...
- 20行以内python代码画出各种减压图
一.太阳花 看到一个很有意思的代码,你若安好,便是晴天!太阳花向你开~ 绘画效果如下: 代码如下: from turtle import * color('red', 'yellow') begin_ ...
- 【netty】(2)---搭建一个简单服务器
netty(2)---搭建一个简单服务器 说明:本篇博客是基于学习慕课网有关视频教学.效果:当用户访问:localhost:8088 后 服务器返回 "hello netty"; ...
- 【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务
前言:采用Client Credentials方式,即密钥key/password,场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似. 让用户通过客户端去获取自己的tok ...
- EF下lambda与linq查询&&扩展方法
1. linq查询数据 WebTestDBEntities db = new WebTestDBEntities(); 1.1 linq查询所有列数据 var userInfoList = from ...
- 『高次同余方程 Baby Step Giant Step算法』
高次同余方程 一般来说,高次同余方程分\(a^x \equiv b(mod\ p)\)和\(x^a \equiv b(mod\ p)\)两种,其中后者的难度较大,本片博客仅将介绍第一类方程的解决方法. ...
- Python爬虫入门教程 4-100 美空网未登录图片爬取
美空网未登录图片----简介 上一篇写的时间有点长了,接下来继续把美空网的爬虫写完,这套教程中编写的爬虫在实际的工作中可能并不能给你增加多少有价值的技术点,因为它只是一套入门的教程,老鸟你自动绕过就可 ...
- 监控mysql
Mysql服务器监控 管理MySql服务器属于应用程序监控范畴.这是因为绝大多数性能参数是有MySql软件产生的,而不属于主操作系统的一部分. 如当前所提到的,应该总是先监控基础操作系统,然后监控My ...