ネットワーク経由で、それぞれサイズが 50 バイトの多数の TCP パケットを送信しています。後で、TCP がいくつかの 50 バイトのパケットを単一の TCP パケットに集約することがわかりました。私の質問は、「C」プログラムで TCP アグリゲーションを回避する方法はありますか?
4 に答える
送信された複数のパケットを 1 つの TCP パケットにパックすることは、Nagle のアルゴリズムとして知られるアルゴリズムを使用して処理されます。無効にするには、ソケットにオプションを設定しTCP_NODELAY
ます。
int flag = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
これにより、ネットワークの効率が低下することに注意してください。各パケットをすぐに送信する必要がない限り、避ける必要があります。
TCP は基本的に、アプリケーション層でパケットベースのサービスを提供しません。純粋なストリーム以上のものを必要とする TCP を使用するアプリケーションは、独自のフレーミング メカニズムを提供する必要があります。
このTCP_NODELAY
オプションにより、各アプリケーションレベルの書き込みが個別のフレームで実行されることがよくありますが (MTU よりも大きい場合を除く)、保証はありません。特に、受信ウィンドウがゼロに縮小された場合 (大量のデータを送信している接続では一般的)、受信ウィンドウが再び開いたときに複数の書き込みを結合することができます。
さらに、送信側の TCP が書き込みを結合しない場合でも、受信側がソケットから 1 回のアプリケーション レベルの読み取りで複数の TCP フレームからのデータを提示するのを止める方法はありません。これは特に、受信側のアプリケーションがそうでない場合に発生します。しばらくスケジュールされているか、接続でパケット損失が発生したとき。
送信側での各アプリケーション レベルの書き込みが、受信側でのアプリケーション レベルの読み取りと正確にペアになるとアプリケーションが想定している場合、まれで再現が難しいバグに備えることになります。
TCP は、定義上、パケット化サービスを提供しません。TCP は、バイト ストリーム指向のプロトコルです。最善の方法は、独自のフレーミング マークをデータに挿入することです。次に、受信者が少なくとも不良フレーム (おそらく集約データ) を検出し、そのようなデータをドロップできれば、目的の場所に到達できます。
send-as-soon-as-possible アプローチ (ala NODELAY) は、受信者がまだデータを集約できるため、動作することが保証されていません。これは、何らかの理由で tcp データが遅延した場合に発生する可能性が高くなります。
1 つの方法は、送信呼び出しで TCP_NODELAY フラグを使用することです。ただし、これがサポートされているかどうかは、TCP スタックに依存します。