在这个用例中,TCP_CORK 和 TCP_NODELAY 之间有什么显着区别吗? [英] Is there any significant difference between TCP_CORK and TCP_NODELAY in this use-case?

查看:25
本文介绍了在这个用例中,TCP_CORK 和 TCP_NODELAY 之间有什么显着区别吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

After writing an answer about TCP_NODELAY and TCP_CORK, I realized that my knowledge of TCP_CORK's finer points must be lacking, since it's not 100% clear to me why the Linux developers felt it necessary to introduce a new TCP_CORK flag, rather than just relying on the application to set or clear the existing TCP_NODELAY flag at the appropriate times.

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

In particular, if I have a Linux application that wants to send() some small/non-contiguous fragments of data over a TCP stream without paying the 200mS Nagle latency-tax, and at the same time minimize the number of packets needed to send it, I can do it either of these two ways:

使用 TCP_CORK(伪代码):

With TCP_CORK (pseudocode):

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(伪代码):

or with TCP_NODELAY (pseudocode):

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() 零字节就足够了.

I've been using the latter technique for years with good results, and it has the benefit of being portable to non-Linux OS's as well (although outside of Linux you have to call send() again after turning Nagle's back off, in order to ensure the packets get sent immediately and avoid the Nagle-delay -- send()'ing zero bytes is sufficient).

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

Now the Linux devs are smart guys, so I doubt that the above usage of TCP_NODELAY never occurred to them. There must be some reason why they felt it was insufficient, which led them to introduce a new/proprietary TCP_CORK flag instead. Can anybody explain what that reason was?

推荐答案

您有两个问题:

  1. 在这个用例中,TCP_CORK 和 TCP_NODELAY 之间有什么显着区别吗?
  2. 一定有某种原因让他们觉得这是不够的,这导致他们引入了一个新的/专有的 TCP_CORK 标志.有人能解释一下这是什么原因吗?

首先看这个堆栈溢出问题,因为它们是相关的,因为该问题通常在不参考您的用例的情况下描述了两者之间的区别.

First see the answers in this Stack Overflow Question, because the are related in the since that question generally describes the difference between the two without reference to your usecase.

  • TCP_NODELAY ON 表示在您收到数据(部分帧)时立即发送,无论您是否有足够的帧用于完整的网络数据包.
  • TCP_NODELAY OFF 表示 Nagles 算法,表示当数据大于 MSS 时发送数据或等待接收确认后再发送较小的数据.
  • TCP_CORK ON 意味着不要发送任何小于 MSS 的数据(部分帧),直到应用程序这么说或直到 200 毫秒之后.
  • TCP_CORK OFF 表示现在发送所有数据(部分帧).
  • TCP_NODELAY ON means send the data (partial frames) the moment you get, regardless if you have enough frames for a full network packet.
  • TCP_NODELAY OFF means Nagles Algoritm which means send the data when it is bigger than the MSS or waiting for the receiving acknowledgement before sending data which is smaller.
  • TCP_CORK ON means don't send any data (partial frames) smaller than the MSS until the application says so or until 200ms later.
  • TCP_CORK OFF means send all the data (partial frames) now.

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

This means in your given use case in the first example no partial frames are sent until the end, but in your second example partial frames with a receiving acknowledgement will be sent.

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

Also the final send in your first example , Nagle's algorithm still applies to the partial frames after the uncorking , where as in the second example it doesn't.

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

The short version is the TCP_NODELAY sends doesn't accumulate the logical packets before sending then as network packets, Nagle's algorithm does according the algorithm, and TCP_CORK does according to the application setting it.

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

A side effect of this is that Nagle's algorithm will send partial frames on an idle connection, TCP_CORK won't.

此外,TCP_CORK 在 2.2 中被引入到 Linux 内核中(特别是 2.1.127 参见 here),但直到 2.5.71 它与 TCP_NODELAY 互斥.例如,在 2.4 内核中,您可以使用一种或另一种,但在 2.6 中,您可以将两者结合使用,并且 TCP_CORK 在应用时将优先.

Additionally TCP_CORK was introduced into the Linux Kernel in 2.2 (specifically 2.1.127 see here), but until 2.5.71 it was mutually exclusive with TCP_NODELAY. E.g In 2.4 kernels you could use one or the other, but in 2.6 you can combine the two, and TCP_CORK will take precedence when it is applied.

关于你的第二个问题.

引用 Linus Torvalds

To quote Linus Torvalds

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

Now, TCP_CORK is basically me telling David Miller that I refuse to play games to have good packet size distribution, and that I wanted a way for the application to just tell the OS: I want big packets, please wait until you get enough data from me that you can make big packets.

基本上,TCP_CORK 是一种反 nagle"标志.这是相反的没有nagle".

Basically, TCP_CORK is a kind of "anti-nagle" flag. It's the reverse of "no-nagle".

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

Another quote also by Linus is regarding usage of TCP_CORK is the following

基本上,只要服务器知道以下模式,TCP_CORK 就很有用其批量转移.这只是大约 100% 的时间与任何类型的文件服务.

Basically, TCP_CORK is useful whenever the server knows the patterns of its bulk transfers. Which is just about 100% of the time with any kind of file serving.

有关更多引用,请参阅 Sendfile 邮件列表讨论的链接.

For more quotes see the link with Sendfile Mailing List Discussion.

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

In summary, in addition to TCP_MAXSEG and MSGMORE when calling writev, TCP_CORK is another tool which allows the application in userspace to have more fine grained control over packet size distribution.

参考资料和进一步阅读

这篇关于在这个用例中,TCP_CORK 和 TCP_NODELAY 之间有什么显着区别吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆