TCP Nagle算法简述

article/2025/10/6 23:57:26
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的包存在于网络,它并不管包的大小,因此它事实上就是一个扩展的停-等协议(停止等待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===========================


http://chatgpt.dhexx.cn/article/wpGh14wZ.shtml

相关文章

倒角算法推导

推导原理基本很简单: 已知AB, BC两条线段,且交于B点,求倒角半径为 L,AB,BC的倒角 以最短边(假定为AB)长 LAB, 在BC中,以B为起点,找出与LAB同长度…

[控制算法]

[常用控制算法] 0.博览众长 0.1 视频 1. DR_CAN b站 0.2 文章 1.控制算法整理 0.3 传统 VS 现代控制算法 1. 传统 传统控制算法:PID,模糊,神经网络控制算法。 2. 现代 现代控制算法有比例,LQR算法(用于线性系统)&#x…

求树的直径证明

树的直径(最长路) 的详细证明 主要是利用了反证法: 假设 s-t这条路径为树的直径,或者称为树上的最长路 现有结论,从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就…

树的直径和树的重心

1.树包括有根树和无根树,有根树是有向图的子图,无根树是无向图的子图,都满足边数等于节点数减一。根是入度为零或没有父亲的节点 2.树的直径:树上最长的简单路径(不重复经过点的路径) 3.求解算法&#xf…

树的直径总结

树的直径 一、定义 在一棵树中,最远的两个子节点之间的距离被称为树的直径; 链接这两个点的路径被称为树的最长链; 有两种求法,时间复杂度均为 O ( n ) O(n) O(n) ; 二、树形DP 1. 状态 由于一个点的最长路通过…

基础算法 - 树的直径

题目地址:https://leetcode-cn.com/problems/tree-diameter/ 1245. 树的直径 难度中等48收藏分享切换为英文接收动态反馈 给你这棵「无向树」,请你测算并返回它的「直径」:这棵树上最长简单路径的 边数。 我们用一个由所有「边」组成的数…

树的直径-c++

题目 实验室里原先有一台电脑(编号为1),最近氪金带师咕咕东又为实验室购置了N-1台电脑,编号为2到N。每台电脑都用网线连接到一台先前安装的电脑上。但是咕咕东担心网速太慢,他希望知道第i台电脑到其他电脑的最大网线长度,但是可怜…

求树的直径算法以及证明

以下为两次dfs(bfs)的做法以及正确性证明。 算法步骤 (1)任取树上一点S,以S为源点BFS得S到各个顶点的d值; (2)取d值最大者之一为P,再以P为源点BFS得P到各个顶点的d值&am…

求树的直径

树的直径,即树上的最长路径,显然,树的直径可以有很多条(考虑一棵菊花)。 接下来我们考虑如何求出一棵树的直径。有很多种O(n)的算法。 算法1:我们任取树中的一个节点x,找出距离它最远的点y&am…

数据结构 树的直径

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。 学习日记 目录 学习日记 一、定义 二、两次DFS 定理: 反证法证明: 1、若y在d(t,s)上 2、若y不在d(s,t)上,且d(y,z)与d(s.t)…

树的直径(最长的简单路径)

题解:分析一下,由于是树,所以两点之间的路径有且只有一条,为了求出欧拉路,所以必然会向回走,从递归的角度来看,假设x看作一个树根,有t个孩子y1…yt。其中每个孩子为根的子树欧拉路都…

树的直径概念及求解

文章目录 1. 使用两次DFS求得树的直径2. 使用树形DP求得树的直径3. 性质4. 参考文献和习题 树上任意两节点之间最长的简单路径即为树的「直径」。显然,一棵树可以有多条直径,他们的长度相等。可以用两次 D F S / B F S DFS/BFS DFS/BFS 或者树形 D P D…

树的直径两种求法

首先先介绍一下什么是树的直径,树的直径就是树中所有最短路经距离的最大值。 求树的直径通常有两种方法,一种是通过两次搜索(bfs和dfs均可),另一种就是通过树形dp来求了。 先来介绍一下用两次深搜来求树的直径&#x…

树的直径的概念

树的直径的定义: 在一棵树中,每一条边都有权值,树中的两个点之间的距离,定义为连接两点的路径上边权之和, 那么树上最远的两个点,他们之间的距离,就被称之为,树的直径。 树的直径的别称&#x…

树的直径

【定义】 我们将一棵树T ( V,E )的直径定义为maxδ ( u,v ) ( u,v ∈ V ),也就是说,树中所有最短路径距离的最大值即为树的直径。 【做法】 例题传送门Cow Marathon(POJ 1985) 对于树的直径…

浅谈树的直径

一、定义: 我们将一棵树T(V,E)的直径定义为max(u,v) (u,v∈V),也就是说,树中所有最短路径距离的最大值即为树的直径。(就是树中的最长路径的长度) 二、求解树德直径: 求得树的直径有两种方法,一…

3.网络基础-三层路由网络

3.1、IP地址 初识IP地址 • 在IP网络中,通信节点需要有一个唯一的IP地址; • IP地址用于IP报文的寻址以及标识一个节点; • IPv4地址一共32bits,使用点分十进制的形式表示; IP地址的分类 E类是保留地址 公有IP及私有…

计算机网络——配置动态路由实验

配置动态路由实验 实验目的实验软件实验要求实验知识实验步骤实验结果 实验目的 掌握 RIP 协议配置。RIP 协议配置的命令为&#xff1a;router(config)#network <connected-network> 其中参数 <connected-network> 表示路由器的直连网络号。 实验软件 Cisco Pac…

路由技术基础

路由技术是在网络拓扑结构中为不同节点的数据提供传输路径的技术&#xff0c;路由选择算法是其核心内容。路由选择算法分为静态路由选择算法和动态路由选择算法。 一.路由基础 1.路由的基本概念 路由、路由器 &#xff08;1&#xff09;路由 路由是指导IP报文从源发送到目…

网络路由交换 -- 静态路由 和 缺省路由

1.IP路由基础 1.什么是静态路由&#xff1f; 静态路由是由管理员手工添加的路由条目&#xff1b;通过静态路由添加的都是非直连网段。 2.静态路由的特点&#xff1f; 静态路由的添加和删除都需要手工完成&#xff1b;静态路由无法适应网络的动态变更&#xff0c;即缺乏适应…