socket中的nagle算法

本文深入解析了TCP/IP协议中的Nagle算法,阐述了其工作原理、应用场景及如何通过TCP_NODELAY和TCP_CORK选项进行控制。同时对比了Nagle算法与CORK算法的区别。

Nagel算法

TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认。为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。(一个连接会设置MSS参数,因此,TCP/IP希望每次都能够以MSS尺寸的数据块来发送数据)。Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。

Nagle算法的基本定义是任意时刻,最多只能有一个未被确认的小段。所谓小段,指的是小于MSS尺寸的数据块,所谓未被确认,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到。

Nagle算法的规则(:

1)如果包长度达到MSS,则允许发送;

2)如果该包含有FIN,则允许发送;

3)设置了TCP_NODELAY选项,则允许发送;

4)未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;

5)上述条件都未满足,但发生了超时(一般为200ms),则立即发送。

Nagle算法只允许一个未被ACK的包存在于网络,它并不管包的大小,因此它事实上就是一个扩展的停-等协议,只不过它是基于包停-等的,而不是基于字节停-等的。Nagle算法完全由TCP协议的ACK机制决定,这会带来一些问题,比如如果对端ACK回复很快的话,Nagle事实上不会拼接太多的数据包,虽然避免了网络拥塞,网络总体的利用率依然很低。

Nagle算法是sillywindowsyndrome(SWS)预防算法的一个半集。SWS算法预防发送少量的数据,Nagle算法是其在发送方的实现,而接收方要做的时不要通告缓冲空间的很小增长,不通知小窗口,除非缓冲区空间有显著的增长。这里显著的增长定义为完全大小的段(MSS)或增长到大于最大窗口的一半。

注意:BSD的实现是允许在空闲链接上发送大的写操作剩下的最后的小段,也就是说,当超过1MSS数据发送时,内核先依次发送完nMSS的数据包,然后再发送尾部的小数据包,其间不再延时等待。(假设网络不阻塞且接收窗口足够大)。

举个例子,一开始client端调用socketwrite操作将一个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.youkuaiyun.com/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算法并不是很复杂,他的主要职责是数据的累积,实际上有两个门槛:一个就是缓冲区中的字节数达到了一定量,另一个就是等待了一定的时间(一般的Nagle算法都是等待200ms);这两个门槛的任何一个达到都必须发送数据了。一般情况下,如果数据流量很大,第二个条件是永远不会起作用的,但当发送小的数据包时,第二个门槛就发挥作用了,防止数据被无限的缓存在缓冲区不是好事情哦。了解了TCPNagle算法的原理之后我们可以自己动手来实现一个类似的算法了,在动手之前我们还要记住一个重要的事情,也是我们动手实现Nagle算法的主要动机就是我想要紧急发送数据的时候就要发送了,所以对于上面的两个门槛之外还的增加一个门槛就是紧急数据发送。

对于我现在每秒钟10次数据发送,每次数据发送量固定在85~100字节的应用而言,如果采用默认的开启Nagle算法,我在发送端,固定每帧数据85个,间隔100ms发送一次,我在接受端(阻塞方式使用)接受的数据是43138交替出现,可能就是这个算法的时间阈值问题,如果关闭Nagle算法,在接收端就可以保证数据每次接收到的都是85帧。

Nagle算法适用于小包、高延迟的场合,而对于要求交互速度的b/sc/s就不合适了。socket在创建的时候,默认都是使用Nagle算法的,这会导致交互速度严重下降,所以需要setsockopt函数来设置TCP_NODELAY1.不过取消了Nagle算法,就会导致TCP碎片增多,效率可能会降低。

关闭nagle算法,以免影响性能,因为控制时控制端要发送很多数据量很小的数据包,需要马上发送

constcharchOpt=1;

intnErr=setsockopt(pContext->m_Socket,IPPROTO_TCP,TCP_NODELAY,&chOpt,sizeof(char));

if(nErr==-1)

{

TRACE(_T("setsockopt()error\n"),WSAGetLastError());

return;

}

<!--EndFragment-->
<think>我们正在处理用户的问题:如何在LabVIEW中禁用Nagle算法?根据引用[1]:禁用Nagle算法可以通过注册表调整来实现,但需要注意的是,禁用Nagle算法可能对文件传输有负面影响,只建议在某些游戏中使用。然而,用户是在LabVIEW环境中,LabVIEW通常使用TCP/IP协议进行网络通信。在LabVIEW中,我们可以通过设置TCP_NODELAY选项来禁用Nagle算法。步骤:1.在LabVIEW中,当使用TCP通信时,我们可以在打开TCP连接后,通过设置套接字选项来禁用Nagle算法。2.具体来说,我们可以使用“TCP SetOption”函数(位于:数据通信->协议->TCP)来设置TCP_NODELAY选项。具体操作:-首先,使用“TCPCreateListener”或“TCP OpenConnection”创建或打开一个TCP连接,得到连接ID。-然后,使用“TCP SetOption”函数,设置选项为TCP_NODELAY(值为1),以禁用Nagle算法。 -之后,进行正常的数据读写。 -最后,关闭连接。注意:TCP_NODELAY选项的常量值,在LabVIEW中通常为1(但具体可能需要查看LabVIEW帮助文档确认)。我们可以通过创建一个常量,输入1,或者使用枚举类型(如果LabVIEW提供)来选择TCP_NODELAY。代码示例(LabVIEW框图):由于LabVIEW是图形化编程,我们无法直接提供文本代码,但可以描述节点连接方式:1.创建TCP监听器或打开TCP连接(根据你的角色是服务器还是客户端)。2.将连接ID传递给“TCPSet Option”函数。3.在“TCPSet Option”函数的“option”输入端,创建一个常量并输入1(代表TCP_NODELAY)或者使用枚举值(如果可用)。4.在“optionvalue”输入端,创建一个布尔值(True)或一个32位整数(1)表示启用TCP_NODELAY(即禁用Nagle算法)。5.然后继续使用该连接进行读写。注意:LabVIEW的TCP函数可能在不同版本中位置略有不同,但函数名类似。另外,根据引用[2]和[3]的内容似乎与问题无关,因此我们主要参考引用[1]的说明,并结合LabVIEW的TCP函数来实现。相关问题:1.在LabVIEW中如何设置TCP套接字选项?2.禁用Nagle算法会对LabVIEW的TCP通信产生什么影响?3.除了禁用Nagle算法,还有哪些方法可以优化LabVIEW的实时网络通信?现在,我们按照用户要求生成回答。</think>### 如何在LabVIEW中禁用Nagle算法 在LabVIEW中禁用Nagle算法需要通过设置TCP套接字的`TCP_NODELAY`选项来实现。Nagle算法通过合并小数据包减少网络流量,但会增加延迟。禁用该算法可提升实时通信性能,尤其适用于需要低延迟的应用(如游戏或实时控制系统)[^1]。以下是具体实现步骤: #### 方法步骤 1. **建立TCP连接** 使用`TCP Open Connection`或`TCP Create Listener`函数创建TCP连接,获取连接ID(connection ID)。 2. **设置TCP_NODELAY选项** - 使用`TCP Set Option`函数(位于:函数选板 → 数据通信 → 协议 → TCP) - 输入参数配置: - `option`:输入常量`1`(对应`TCP_NODELAY`选项) - `option value`:输入布尔值`True`(禁用Nagle算法) - `connection in`:连接步骤1获取的连接ID ```plaintext [TCP连接ID] → TCP Set Option (option=1, value=True) → [修改后的连接ID] ``` 3. **数据传输** 使用修改后的连接ID进行`TCP Write`/`TCP Read`操作。 4. **关闭连接** 最后用`TCP Close Connection`关闭连接。 #### 注意事项 - **适用场景**:仅建议在需要低延迟的实时应用中使用(如游戏控制、传感器实时传输)。常规文件传输可能因禁用Nagle算法导致吞吐量下降[^1]。 - **平台差异**:Windows系统可能需要额外注册表修改(`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces`下新建`TcpAckFrequency`=1和`TCPNoDelay`=1)[^1]。 - **LabVIEW版本**:2013及以上版本直接支持`TCP Set Option`函数。 #### 替代方案 若需更精细控制,可调用Windows API: 1. 使用`Call Library Function Node`调用`ws2_32.dll`的`setsockopt`函数 2. 参数设置: ```c setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&enable, sizeof(enable)); ``` (`enable=1`表示禁用Nagle) --- ### 相关问题 1. 禁用Nagle算法后如何验证LabVIEW网络延迟确实降低? 2. LabVIEW中TCP_NODELAY与UDP协议在实时通信中的优劣对比? 3. 除了禁用Nagle算法,还有哪些方法能优化LabVIEW的实时网络性能?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值