【网络编程实践】2.3.4.2 建议关闭 Nagle 算法

article/2025/7/23 4:37:25

Nagle算法主要是避免发送小的数据包,要求TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。

Nagle算法的目的:避免发送大量的小包,网络上每次只能一个小包存在,在小包被确认之前,只能积累发送大包,如果包长度达到MSS,则允许发送;如果该包含有FIN,则允许发送;但发生了超时(一般为200ms),则立即发送, 启动TCP_NODELAY,就意味着禁用了Nagle算法

Nagle算法会严重影响请求响应式协议的延迟
如果我们的程序设计的不够合理,Nagle算法可能会增加程序的延迟。

如果你的程序是 write-write-read 模式,在使用了Nagle算法后,第二个 write 就会被推后一个RRT发送而造成一个很长的ack等待,从而产生一个延迟。为了避免这种情况,一般建议在应用层做缓冲,将两个write合在一起,成为 write-read。

但是还有一种情况是,在一个连接上并发的有多个请求时,我们很难将数据整合在一起,它们来自程序中不同的位置。而这种情况Nagle算法会大大增加程序的延迟。

因此,如果你没有十足的把握驾驭Nagle算法的话,我们建议使用 TCP_NODELY 关闭Nagle算法。

示例:观察 Nagle算法 的延迟

服务器端代码:recipes/tpc/nodelay_server.cc
客户端代码:recipes/tpc/nodelay.cc

而代码的逻辑也很简单。客户端是一个 write-write-read 程序,通过制定参数 对比 采取不同TCP选项下程序的延迟情况。

// nodelay_server.cc 服务端代码部分
// 处理逻辑:收header ——》收数据 ——》回响应
//...
int main(int argc, char* argv[])
{//...bool nodelay = argc > 1 && strcmp(argv[1], "-D") == 0;while (true){TcpStreamPtr tcpStream = acceptor.accept();printf("accepted no. %d client\n", ++count);if (nodelay)tcpStream->setTcpNoDelay(true);while (true){int len = 0;	// 收headerint nr = tcpStream->receiveAll(&len, sizeof len);if (nr <= 0)break;printf("%f received header %d bytes, len = %d\n", now(), nr, len);assert(nr == sizeof len);std::vector<char> payload(len);	// 收数据nr = tcpStream->receiveAll(payload.data(), len);printf("%f received payload %d bytes\n", now(), nr);assert(nr == len);		// 回响应int nw = tcpStream->sendAll(&len, sizeof len);assert(nw == sizeof len);}printf("no. %d client ended.\n", count);}
}
  double start = now();for (int n = 0; n < num; ++n){printf("Request no. %d, sending %d bytes\n", n, len);if (buffering)	// 如果设置缓冲,我们将header与数据合在一起发送{std::vector<char> message(len + sizeof len, 'S');memcpy(message.data(), &len, sizeof len);int nw = stream->sendAll(message.data(), message.size());printf("%.6f sent %d bytes\n", now(), nw);}else	// 如果没有设置缓冲,分两次发送header和数据{stream->sendAll(&len, sizeof len);printf("%.6f sent header\n", now());usleep(1000); // prevent kernel merging TCP segmentsstd::string payload(len, 'S');int nw = stream->sendAll(payload.data(), payload.size());printf("%.6f sent %d bytes\n", now(), nw);}}

编译服务端代码:g++ -o nodelay_server nodelay_server.cc Acceptor.cc InetAddress.cc TcpStream.cc Socket.cc -lpthread -std=c++11
编译客户端代码:g++ -o nodelay nodelay.cc Acceptor.cc InetAddress.cc TcpStream.cc Socket.cc -lpthread -std=c++11

测试:使用ping命令,可以看到正常的RTT约31ms延迟。然后执行程序,大概有61ms的延迟,是RTT的两倍。
在这里插入图片描述

使用 buffering 选项,可以看到延迟减少到35ms左右。
在这里插入图片描述
通过tcpdump我们可以看到,客户端一次发送了 1005 个字节的数据。客户端 write-read
在这里插入图片描述


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

相关文章

Nagle算法与TCP_CORK,TCP_NODELAY,TCP_QUICKACK

1. Nagel算法 TCP/IP协议中&#xff0c;无论发送多少数据&#xff0c;总是要在数据前面加上协议头&#xff0c;同时&#xff0c;对方接收到数据&#xff0c;也需要发送ACK表示确认。为了尽可能的利用网络带宽&#xff0c;TCP总是希望尽可能的发送足够大的数据。&#xff08;一…

如何关闭和启用Nagle算法

如果各位读者在搜索如何关闭的话&#xff0c;那么我有理由相信各位对想要解决的问题已经算是比较清楚了&#xff0c;废话不多数。 什么是nagle算法&#xff0c;它是干嘛用的&#xff0c;请自行google or 百度 Step1 Open regredit 快捷键&#xff1a;winr 打开&#xff1a…

19- TCP 协议(Nagle)

前面我们所用的 unp/protocol/tools/winclient/echo_cli.cpp 程序的特别之处是它总会发送一个小分组&#xff08;TCP 段&#xff0c;只有 41 字节&#xff09;到服务器。这样的小分组在英文中称为 tinygram&#xff0c;在网络状态好的情况下&#xff0c;比如局域网中&#xff0…

TCP Nagle算法详解

转: http://bbs.chinaunix.net/thread-3767363-1-1.html 在网络拥塞控制领域&#xff0c;我们知道有一个非常有名的算法叫做Nagle算法&#xff08;Nagle algorithm&#xff09;&#xff0c;这是使用它的发明人John Nagle的名字来命名的&#xff0c;John Nagle在1984年首次用这个…

TCP之延时Nagle算法实验详解

TCP/IP协议中&#xff0c;无论发送多少数据&#xff0c;总是要在数据前面加上协议头&#xff0c;同时&#xff0c;对方接收到数据&#xff0c;也需要发送ACK表示确认。为了尽可能的利用网络带宽&#xff0c;TCP总是希望尽可能的发送足够大的数据。&#xff08;一个连接会设置MS…

Nagle Algorithm

转: http://bbs.chinaunix.NET/thread-3767363-1-1.html 在网络拥塞控制领域&#xff0c;我们知道有一个非常有名的算法叫做Nagle算法&#xff08;Nagle algorithm&#xff09;&#xff0c;这是使用它的发明人John Nagle的名字来命名的&#xff0c;John Nagle在1984年首次用这…

TCP中的Nagle算法

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

确认应答、Nagle算法和延时确认应答

目录 确认应答 延时确认应答 Nagle算法 确认应答 TCP在传输数据的时候&#xff0c;每次接受方收到来自发送方的数据包后&#xff0c;接受方对都会发送一个确认应答(ACK)报文作为回应&#xff0c;发送方收到来自接受方的确认应答(ACK)报文&#xff0c;就表明发送的数据已经被…

TCP/IP卷一:80---TCP数据流与窗口管理之(延时确认(延迟ACK)、Nagle算法)

一、延迟确认&#xff08;延迟ACK&#xff09; 在许多情况下&#xff0c;TCP并不对每个到来的数据包都返回ACK&#xff0c;利用TCP的累积ACK字段&#xff08;参见TCP报文格式https://blog.csdn.net/qq_41453285/article/details/104016416&#xff09;就能实现该功能累积确认可…

禁用 Nagle 算法

有没有发现一个很奇怪的组合&#xff0c;即 Nagle 算法和延时 ACK 的组合。这个组合为什么奇怪呢&#xff1f; 我举一个例子你来体会一下。比如&#xff0c;客户端分两次将一个请求发送出去&#xff0c;由于请求的第一部分的报文未被确认&#xff0c;Nagle 算法开始起作用&…

TCP Nagle算法及示例

TCP nagle算法是说&#xff0c;一个TCP连接只允许有一个未被确认的小数据包&#xff0c;如果有小数据包未被确认&#xff0c;其他要发送的小数据包先被缓存起来&#xff0c;等收到确认后&#xff0c; 把这些数据包再一块发送出去。注意算法中说的是小数据包&#xff0c;也就是n…

TCP-IP详解:Nagle算法

参考书籍&#xff1a;TCP/IP详解&#xff0c;卷1&#xff1a;协议 Small Packet Problem 在使用一些协议通讯的时候&#xff0c;比如Telnet&#xff0c;会有一个字节字节的发送的情景&#xff0c;每次发送一个字节的有用数据&#xff0c;就会产生41个字节长的分组&#xff0c…

TCP-Nagle:代码版本重新解释Nagle算法

开年来的第一份工作&#xff0c;就是在最新的内核上打补丁。 可没想到Nagle算法也被我冲进了去年的垃圾桶里。 在网上找了一些资料&#xff0c;理论很快被消化&#xff0c;但看了看内核的实现&#xff0c;久久没能动弹。坐了一天&#xff0c;才摸索出来点什么&#xff0c;觉得…

Nagle算法原理与实现详解

文章目录 背景Nagle算法详解算法实现实现开启与关闭Nagle算法 Nagle算法与延迟ACK参考 背景 TCP的数据流大致可以被分成两类&#xff1a; 交互式数据流 TCP交互数据流指的是&#xff1a;TCP连接中传输的所有数据的总和&#xff0c;包括控制命令&#xff08;用于管理网络中连接…

TCP详解 (三)Nagle算法和延迟确认

文章目录 延迟确认Nagle算法Nagle算法遇上延迟确认关闭Nagle算法 一些有关TCP通信量的研究如[Caceresetal.1991]发现&#xff0c;如果按照分组数量计算&#xff0c;约有一半的TCP报文段包含成块数据&#xff08;如 FTP、电子邮件和 Usenet新闻&#xff09;&#xff0c;另一半则…

复指数信号正交性的简单证明

复指数信号为&#xff1a; . 写成矢量形式&#xff1a; 复指数信号两两正交&#xff0c;也就是两个复指数信号的内积有如下表示&#xff1a; 将上式内积形式展开&#xff1a; 当kl时&#xff0c;所有cos项1&#xff0c;sin项0&#xff0c;求和为N。 当时&#xff0c;将求和符…

三角函数正交性的推导

定理&#xff1a; 一个三角函数系&#xff1a;1 cosx sinx cos 一个三角函数系&#xff1a;1&#xff0c;cosx , sinx , cos2x , sin2x , … , cosnx , sinnx , … 如果这一堆函数&#xff08;包括常数1&#xff09;中任何两个不同函数的乘积在区间[-π, π]上的积分等于…

OFDM时频脉冲形状与子载波正交性的理解

从多载波调制的角度来理解子载波间正交&#xff0c;首先要明确OFDM默认的脉冲成型是时域矩形窗&#xff0c;时域上每个子载波 e j 2 π f n t e^{j2πf_nt} ej2πfn​t 都被一个矩形窗脉冲 g T ( t ) g_T(t) gT​(t)成型。其次&#xff0c;OFDM子载波间隔 等于 OFDM符号周期的…

正交性原理与维纳霍夫(正则)方程

有期望信号d&#xff08;n&#xff09;&#xff0c;纯净信号x&#xff08;n&#xff09;&#xff0c;以及噪声信号g&#xff08;n&#xff09;; 有滤波器h&#xff08;m&#xff09;,以及滤波器输出信号y&#xff08;n&#xff09;&#xff0c;滤波器输出纯净信号x的估计值y&a…