17

TCP_NODELAY と TCP_CORK に関する回答を書いた後、TCP_CORK の細かい点に関する知識が不足しているに違いないことに気付きました。なぜなら、Linux 開発者が新しい TCP_CORK フラグに頼るのではなく、新しい TCP_CORK フラグを導入する必要があると感じた理由が 100% 明確ではないからです。アプリケーションを使用して、適切なタイミングで既存の TCP_NODELAY フラグを設定またはクリアします。

特に、200 ミリ秒の Nagle 遅延税を支払うことなく、TCP ストリームを介していくつかの小さな/不連続なデータ フラグメントを send() したい Linux アプリケーションがある場合、同時に送信に必要なパケット数を最小限に抑えます。それは、次の 2 つの方法のいずれかで実行できます。

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以外のOSにも移植できるという利点があります.パケットがすぐに送信されるようにし、Nagle 遅延を回避するには -- send()'ing 0 バイトで十分です)。

現在、Linux 開発者は賢い人なので、上記の TCP_NODELAY の使用法が彼らにまったく思い浮かばなかったとは思えません。彼らが不十分だと感じたのには何らかの理由があるに違いありません。そのため、代わりに新しい/独自の TCP_CORK フラグを導入することになりました。その理由を説明できる人はいますか?

4

1 に答える 1

22

2 つの質問があります。

  1. このユースケースでは、TCP_CORK と TCP_NODELAY の間に大きな違いはありますか?
  2. 彼らが不十分だと感じたのには何らかの理由があるに違いありません。そのため、代わりに新しい/独自の TCP_CORK フラグを導入することになりました。その理由を説明できる人はいますか?

最初にこのStack Overflow Questionの回答を参照してください。なぜなら、その質問は通常、ユースケースを参照せずに 2 つの違いを説明しているためです。

  • TCP_NODELAY ONは、完全なネットワーク パケットに対して十分なフレームがあるかどうかに関係なく、取得した瞬間にデータ (部分フレーム) を送信することを意味します。
  • TCP_NODELAY OFFは Nagles アルゴリズムを意味します。これは、MSS よりも大きいデータを送信するか、受信確認を待ってから小さいデータを送信することを意味します。
  • TCP_CORK ONは、アプリケーションがそう言うまで、または 200 ミリ秒後まで、MSS より小さいデータ (部分フレーム) を送信しないことを意味します。
  • TCP_CORK OFFは、すべてのデータ (部分フレーム) をすぐに送信することを意味します。

これは、最初の例の特定の使用例では部分フレームが最後まで送信されないことを意味しますが、2 番目の例では受信確認を伴う部分フレームが送信されます。

また、最初の例の最後の送信である Nagle のアルゴリズムは、2 番目の例のように、uncorking 後の部分フレームにも適用されます。

短いバージョンは、TCP_NODELAY が送信する前に論理パケットを蓄積せず、ネットワーク パケットとして送信することです。Nagle のアルゴリズムはアルゴリズムに従って行い、TCP_CORK はアプリケーションの設定に従って行います。

これの副作用は、Nagle のアルゴリズムがアイドル状態の接続で部分的なフレームを送信することですが、TCP_CORK は送信しません。

さらに、TCP_CORK は 2.2 で Linux カーネルに導入されました (特に 2.1.127 はこちらを参照) が、2.5.71 までは TCP_NODELAY と相互に排他的でした。たとえば、2.4 カーネルではどちらか一方を使用できますが、2.6 では 2 つを組み合わせることができ、TCP_CORK が適用されると優先されます。

2番目の質問について。

ライナス・トーバルズを引用する

さて、TCP_CORK は基本的に私が David Miller に、適切なパケット サイズの分散を実現するためにゲームをプレイすることを拒否し、アプリケーションが OS に「大きなパケットが必要です。十分なデータが得られるまで待ってください」と伝える方法が必要であることを伝えています。あなたは大きなパケットを作ることができると思います。

基本的に、TCP_CORK は一種の「アンチネーグル」フラグです。「ノーネーグル」の逆です。

Linus による別の引用は、TCP_CORK の使用に関する次のとおりです。

基本的に、TCP_CORK は、サーバーがバルク転送のパターンを知っている場合に役立ちます。これは、あらゆる種類のファイル サービングでほぼ 100% の時間です。

その他の引用については、Sendfile メーリング リスト ディスカッションのリンクを参照してください。

要約すると、writev を呼び出すときの TCP_MAXSEG と MSGMORE に加えて、TCP_CORK は、ユーザー空間のアプリケーションがパケット サイズの分散をより細かく制御できるようにする別のツールです。

参考資料と参考資料

于 2014-03-05T06:06:27.267 に答える