【问题标题】:Is there any significant difference between TCP_CORK and TCP_NODELAY in this use-case?在这个用例中,TCP_CORK 和 TCP_NODELAY 之间有什么显着区别吗?
【发布时间】:2014-04-03 03:55:08
【问题描述】:

在写了一个关于 TCP_NODELAY 和 TCP_CORK 的answer 之后,我意识到我对 TCP_CORK 更精细点的了解一定是缺乏的,因为我不是 100% 清楚为什么 Linux 开发人员认为有必要引入一个新的 TCP_CORK 标志,而不是而不是仅仅依靠应用程序在适当的时候设置或清除现有的 TCP_NODELAY 标志。

特别是,如果我有一个 Linux 应用程序想要通过 TCP 流发送()一些小的/不连续的数据片段而不支付 200 毫秒 Nagle 延迟税,同时最小化数据包的数量需要发送它,我可以通过以下两种方式之一:

使用 TCP_CORK(伪代码):

int optval = 1;
setsockopt(sk, SOL_TCP, TCP_CORK, &optval, sizeof(int));   // put a cork in it
send(sk, ..);
send(sk, ..);
send(sk, ..);
optval = 0;
setsockopt(sk, SOL_TCP, TCP_CORK, &optval, sizeof(int));   // release the cork

或使用 TCP_NODELAY(伪代码):

int optval = 0;
setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));   // turn on Nagle's
send(sk, ..);
send(sk, ..);
send(sk, ..);
optval = 1;
setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));   // turn Nagle's back off

多年来,我一直在使用后一种技术并取得了不错的效果,而且它还具有可移植到非 Linux 操作系统的好处(尽管在 Linux 之外,您必须在关闭 Nagle 后再次调用 send() ,以确保数据包立即发送并避免 Nagle 延迟 -- send()'ing 零字节就足够了)。

现在 Linux 开发人员都是聪明人,所以我怀疑他们从来没有想到过 TCP_NODELAY 的上述用法。一定有他们觉得它不够的原因,这导致他们引入了一个新的/专有的 TCP_CORK 标志。谁能解释这是什么原因?

【问题讨论】:

    标签: linux tcp nagle


    【解决方案1】:

    你有两个问题:

    1. 在此用例中,TCP_CORK 和 TCP_NODELAY 之间是否有任何显着差异?
    2. 他们觉得它不够用一定是有原因的,这导致他们引入了一个新的/专有的 TCP_CORK 标志。谁能解释这是什么原因?

    首先查看此Stack Overflow Question 中的答案,因为它们与该问题相关,因为该问题通常描述了两者之间的区别,而没有参考您的用例。

    • TCP_NODELAY ON 表示在获得数据的那一刻发送数据(部分帧),无论您是否有足够的帧用于完整的网络数据包。
    • TCP_NODELAY OFF表示Nagles算法,表示大于MSS时发送数据或等待接收确认后再发送较小的数据。
    • TCP_CORK ON 表示在应用程序要求或 200 毫秒后不发送任何小于 MSS 的数据(部分帧)。
    • TCP_CORK OFF 表示现在发送所有数据(部分帧)。

    这意味着在第一个示例的给定用例中,直到最后都不会发送部分帧,但在第二个示例中,将发送带有接收确认的部分帧。

    也是第一个示例中的最终发送,Nagle 的算法仍然适用于 uncorking 之后的部分帧,而在第二个示例中则不适用。

    简短的版本是 TCP_NODELAY 发送在发送之前不会累积逻辑数据包然后作为网络数据包发送,Nagle 的算法根据算法进行,而 TCP_CORK 根据应用程序设置它。

    这样做的副作用是 Nagle 的算法将在空闲连接上发送部分帧,而 TCP_CORK 不会。

    另外,TCP_CORK 在 2.2 中被引入 Linux 内核(特别是 2.1.127,请参阅here),但在 2.5.71 之前,它与 TCP_NODELAY 互斥。例如,在 2.4 内核中,您可以使用其中一个,但在 2.6 中,您可以将两者结合起来,应用时 TCP_CORK 将优先。

    关于你的第二个问题。

    引用 Linus Torvalds 的话

    现在,TCP_CORK 基本上是我告诉大卫米勒我拒绝玩 具有良好数据包大小分布的游戏,并且我想要一种方法 应用程序只告诉操作系统:我想要大数据包,请等到 你从我这里得到足够的数据,你可以制作大数据包。

    基本上,TCP_CORK 是一种“anti-nagle”标志。这是相反的 “没有问题”。

    Linus 的另一个引述是关于 TCP_CORK 的使用如下

    基本上,只要服务器知道 它的批量转移。这只是大约 100% 的时间与任何类型的 文件服务。

    有关更多报价,请参阅 Sendfile 邮件列表讨论的链接。

    总之,除了调用 writev 时的 TCP_MAXSEG 和 MSGMORE 之外,TCP_CORK 是另一个工具,它允许用户空间中的应用程序对数据包大小分布进行更细粒度的控制。

    参考资料和进一步阅读

    【讨论】:

    • 如果我没看错你的描述,Nagle-enabled-mode 和 TCP_CORK-enabled-mode 之间的唯一区别是使用 TCP_CORK-enabled-mode,本地 TCP 堆栈不会等待发送前收到的ACK数据包。这是准确的,还是我仍然错过了什么?
    • 主要区别在于等待收到的确认以及对逻辑到物理数据包分配的影响以及在应用伪代码后是否缓冲发送后的部分帧。如问题所述,在 TCP_CORK 用例中使用 Nagle 算法进行缓冲,但不使用 TCP_NODELAY 用例进行缓冲。
    • 所以最好的做法是先setsockopt(TCP_NODELAY, 1),再setsockopt(TCP_CORK, 1);发送(标题);发送(part_body);发送(left_body); setsockopt(TCP_CORK, 0)?
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 2020-03-09
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多