据我所知,我们有一个套接字选项 SO_TCP_NODELAY 来禁用 Nagle 算法,我发现它是在 TCP/IP 堆栈中实现的https://elixir.bootlin.com/linux/v4.4.90/source/net/ipv4/tcp.c#L2401。但是,我不知道Nagle算法在内核中实现的源代码在哪里。如果你知道的话,可以帮我一下吗?
答案1
简短回答:net_ipv4_tcp_output.c 中的 tcp_nagle_check()
可以在代码中看到避免Nagle的条件:
/* Return false, if packet can be sent now without violation Nagle's rules:
* 1. It is full sized. (provided by caller in %partial bool)
* 2. Or it contains FIN. (already checked by caller)
* 3. Or TCP_CORK is not set, and TCP_NODELAY is set.
* 4. Or TCP_CORK is not set, and all sent packets are ACKed.
* With Minshall's modification: all sent small packets are ACKed.
*/
static bool tcp_nagle_check(bool partial, const struct tcp_sock *tp,
int nonagle)
{
return partial &&
((nonagle & TCP_NAGLE_CORK) ||
(!nonagle && tp->packets_out && tcp_minshall_check(tp)));
}
此函数的可能调用堆栈可能是 tcp_sendmsg_locked()->tcp_push()->__tcp_push_pending_frames()->tcp_write_xmit()->tcp_nagle_test()->tcp_nagle_check() tcp_sendmsg_locked() (在 net/ipv4/tcp.c 中)主要功能是发送数据。每次调用该函数时,它都会从套接字获取一个数据段并准备传输。 Nagle 算法是一种聚合通过套接字到达的数据以优化传输流的优化算法。您可能还想查看TCP 开塞和自动开塞,因为它们的工作方式与 Nagle 类似,但可能优先于 NO_DELAY 选项。为了确保您的数据包发送没有任何延迟,请捕获它们(使用 tcpdump)并验证发送的数据包大小仅比您从应用程序发送的数据大小稍大一点(由于添加了标头)。