在这个用例中,TCP_CORK和TCP_NODELAY之间是否有任何显着差异?

时间:2014-03-02 05:06:18

标签: linux tcp nagle

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

特别是,如果我有一个Linux应用程序想要通过TCP流发送()一些小的/非连续的数据片段而不支付200mS的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-delay - send()'零字节就足够了。

现在Linux开发人员都很聪明,所以我怀疑上面对TCP_NODELAY的使用从未发生过。必须有一些理由让他们认为这是不够的,这导致他们引入了一个新的/专有的TCP_CORK标志。任何人都可以解释一下这个原因是什么吗?

1 个答案:

答案 0 :(得分:18)

你有两个问题:

  1. 在这个用例中,TCP_CORK和TCP_NODELAY之间是否有任何显着差异?
  2. 必须有一些理由让他们认为这是不够的,这导致他们引入了一个新的/专有的TCP_CORK标志。任何人都能解释一下这是什么原因吗?
  3. 首先看一下这个Stack Overflow Question中的答案,因为这个问题与之相关,因为这个问题通常描述了两者之间的区别而没有引用你的用例。

    • TCP_NODELAY ON 表示一旦发送数据(部分帧),无论您是否有足够的帧用于完整的网络数据包。
    • TCP_NODELAY OFF 表示Nagles算法,这意味着在数据大于MSS时发送数据或在发送较小数据之前等待接收确认。
    • TCP_CORK ON 表示在应用程序显示之前或直到200ms之后,不会发送任何小于MSS的数据(部分帧)。
    • TCP_CORK OFF 表示现在发送所有数据(部分帧)。

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

    同样是你的第一个例子中的最后一个发送,Nagle的算法仍然适用于在解开后的部分帧,而在第二个例子中它没有。

    短版本是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基本上是我告诉David Miller,我拒绝参加比赛   游戏有很好的数据包大小分布,我想要一个方法   应用程序告诉操作系统:我想要大包,请等到   你从我这里得到足够的数据,你可以制作大包。

         

    基本上,TCP_CORK是一种“反nagle”旗帜。这是相反的   “无内格尔”。

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

      

    基本上,只要服务器知道模式,TCP_CORK就很有用   它的批量转移。在任何一种情况下,这只是大约100%的时间   文件服务。

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

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

    参考和进一步阅读