如何在Linux中禁用Nagle算法?

15
有没有通过命令行来实现的方法?man tcp告诉我需要设置tcp_nodelay=1,但是我无法在/proc/sys/net/ipv4下创建tcp_nodelay文件。请告诉我是否有在Linux中禁用Nagle的方法。

你想要这个成为系统范围内的吗? - Vaughn Cato
是的,理想情况下我希望它在整个系统中生效。 - Jason Marks
1个回答

40

这个标记(TCP_NODELAY)是一种可以在每个套接字上启用的选项,当创建TCP套接字时应用。这样做是有目的的:Nagle算法通常很有用,有助于处理网络拥塞。我怀疑您不希望在系统范围内禁用它,因为这样会导致您的系统受到此禁用的影响。

要禁用给定套接字的标志,可以按照此处此处的说明,在C语言中应用TCP_NODELAY选项:

int flag = 1;
int result = setsockopt(sock,            /* socket affected */
                        IPPROTO_TCP,     /* set option at TCP level */
                        TCP_NODELAY,     /* name of option */
                        (char *) &flag,  /* the cast is historical cruft */
                        sizeof(int));    /* length of option value */
 if (result < 0)
    ... handle the error ...
你可能需要根据你的编程语言进行调整,但基本上它会将 TCP_NODELAY 标志选项设置到套接字 sock 上,有效地禁用 Nagle 算法。这在任何支持 TCP 标准的操作系统上都是有效的。
如果您仍希望在系统范围内禁用 Nagle 算法,则有两个选项可用。首先,您可以使用相应的标志重新编译您的内核(请参阅您的发行版手册)。第二个选项是创建一个软件,在每个现有连接上设置 TCP_NODELAY 标志,类似于 这段代码。后一选项应该在系统创建新的 TCP 连接时执行。
更干净的方法是激活 TCP 的低延迟模式:
echo 1 > /proc/sys/net/ipv4/tcp_low_latency

更新: tcp_low_latency已在内核v4.14及以上版本中删除。

这将为TCP堆栈提供提示,以便做出哪些决策以降低延迟(我猜这就是通过禁用Nagle算法来实现的)。默认情况下,它被设置为优化带宽(从/proc/sys/net/ipv4/tcp_low_latency读取“0”)。


你的回答是正确的,但为什么要将&flag转换为char *setsockopt需要一个const void *值指针,因此不需要强制转换到某个类型(每种类型都可以隐式转换为void *):http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html 实际上,您甚至违反了C标准,因为将类型A的指针强制转换为类型B的指针,在其中没有一种类型是void *实际上是未定义行为,按照ISO-C来说。 您有一个指向int的指针,但您声称它是指向char *的指针(在几乎所有系统上都可以工作,但在技术上是未定义的)。 - Mecki
这段代码不是我写的,而是我按照第二个链接进行了复制粘贴。你可能需要联系www.unixguide.net解决这个问题。我记得看到过几种不同的`setsockopt()`签名,其中一些(比如我提供的第一个链接)使用`char *作为flag参数。只要有可信的setsockopt()`原型和执行所需操作的代码示例的参考,我不介意改变答案。 - Soravux
与Soravux达成一致:来自Microsoft MSDN的内容:int setsockopt(SOCKET s,int level,int optname,const char * optval,int optlen); 来自Linux man页面的内容:int setsockopt(int sockfd,int level,int optname,const void * optval,socklen_t optlen); 来自vxWorks socklib的内容:STATUS setsockopt(int s,int level,int optname,char * optval,int optlen);来自IBM aix 7.1的内容:int setsockopt(Socket,Level,OptionName,OptionValue,OptionLength)int Socket,Level,OptionName; const void * OptionValue; socklen_t OptionLength; - Pierre
6
请注意,从内核版本v4.14开始,tcp_low_latency已不再起作用。 - Spitfire19

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接