9.3 TCP_NODELAY
2025/12/11大约 4 分钟
9.3 TCP_NODELAY
用来控制是否开启 Nagle 算法
Nagle 算法
info
只有收到前一数据的ACK消息时,Nagle 算法才发送下一数据
书中的示例:
经由tcp发送的数据首先到达TCP socket 的发送缓冲区。
- 假设发送字符串 'Nagle',每个字符间隔一段时间依次达到发送缓冲区。
- ’N‘前面没有其他数据('N’是第一包用户数据)
- 使用Nagle时,在收到 ‘N’ 的ACK前,‘a’、‘g’,‘l',’e' 都已经达到缓冲区
- 不使用Nagle时,只要缓冲区接收到数据就立即发送,不等待ACK
问题:为什么sequenceDiagram 中 第二个group box的第一条消息显示在了前一个box的最后一条消息的下面?在sequenceDiagram 中后出现的就要显示在下面?不能并排?主要是这两个box之间没有关联,相互独立。如果有消息传递那后出现的在下面算是合理。暂时换一种方式,分为两个代码块,避免显示补全导致的拖动。
问:
- 采用Nagle时,如果一直没有收到前面数据的ACK 会怎么样?重新发送前面的数据?判定为连接断开?
- 采用Nagle时,如果缓冲区满了怎么办?
- 采用Nagle 和 不采用Nagle时,发送数据的条件分别是什么?接受前面数据ACK 是否是唯一的条件?
相关信息
TCP套接字默认使用Nagle算法交换数据,因此最大限度地进行缓冲,直到收到ACK。
对上面这段话,我的理解:
使用Nagle时,发送数据有两种情况,1. 收到ACK;2. 缓冲区满。
完成字符串所需的数据包
| 是否启用Nagle | 数据包数量 |
|---|---|
| 启用 | 4 |
| 不启用 | 10 |
对比启用 和 关闭 Nagle 算法,Nagle 能够减少数据包(不必要的流量-头信息)。
相关信息
网络流量未受太大影响时,不使用Nagle算法要比使用它时传输速度快。
在传输大文件数据时:
- 传输的数据比较多,数据包数量多。
- 填充缓冲区的速度比较快
如果使用Nagle,假设从上一包数据发送到接收到ACK 平均耗时1s,1000包数据就多等待1000s。写入缓冲比较快,相当于流水线前道工序做的快,后面的工序慢 就浪费了前面的工作效率。
关闭Nagle可以快速的把数据发送出去,不用经过了漫长的等待时间。
等待ACK既有优点,也有缺点。不同的情况下权衡利弊,做出合理的选择。
关闭Nagle,缓冲区满了就会发送数据。假设发送了1000包,TCP缓冲容量10包,TCP是怎么保证可靠传输的?是即使关闭了Nagle,也限制了在 TCP缓冲容量范围内的包确认后才可以继续发送,还是有其他机制?设置
#include <netinet/tcp.h>
int opt_val;
socklen_t optlen;
optlen = sizeof(opt_val);
getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*) &opt_val, &optlen);
printf("TCP_NODELAY:%d\n", opt_val);
opt_val = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*) &opt_val, optlen);| 行号 | 功能 | 说明 |
|---|---|---|
| 1-6 | 查看当前TCP_NODELAY的值 | 默认开启Nagle算法,TCP_NODELAY值为0 |
| 8-9 | 设置为NODELAY | 关闭Nagle算法 |
测试
暂时想到的两种方法:
- 控制ACK的回复:可控制的ACK回复,或者 是模拟的网络阻塞、传输缓慢
- 控制写入缓冲区:这个要怎么搞?手写驱动?