POSIX ソケットの送信側をリモート エンドまでフラッシュするための標準呼び出しはありますか、それともユーザー レベル プロトコルの一部として実装する必要がありますか? 通常のヘッダーを見回しましたが、何も見つかりませんでした。
9 に答える
TCP_NODELAY を設定してリセットするよりもどうでしょうか? おそらく、重要なデータを送信する直前、またはメッセージの送信が完了したときに行うことができます.
send(sock, "notimportant", ...);
send(sock, "notimportant", ...);
send(sock, "notimportant", ...);
int flag = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
send(sock, "important data or end of the current message", ...);
flag = 0;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
Linuxのマニュアルページにあるように
TCP_NODELAY ... このオプションを設定すると、保留中の出力が明示的にフラッシュされます ...
したがって、おそらくメッセージの後に設定する方がよいでしょうが、他のシステムでどのように機能するかはわかりません
Unix ドメイン ソケットの場合は を使用できますがfflush()
、おそらくネットワーク ソケットを意味していると思います。それらをフラッシュするという概念は実際にはありません。最も近いものは次のとおりです。
セッションの最後に
shutdown(sock, SHUT_WR)
、ソケットへの書き込みを閉じるために呼び出します。TCP ソケットでは、 sockopt を使用して Nagle アルゴリズムを無効にします
TCP_NODELAY
。これは、最初の調査で問題が解決されたように見えても、通常、希望することを確実に実行できないひどい考えです。
ユーザープロトコルレベルで「フラッシュ」を必要とする問題を処理することが正しいことになる可能性が非常に高いです。
私が認識している標準の TCP/IP ソケット インターフェイスでは、データを「リモート エンドまでずっと」フラッシュし、それが実際に確認されていることを確認する方法はありません。
一般的に言えば、プロトコルでデータの「リアルタイム」転送が必要な場合、一般的に行う最善の方法は、 の を設定することsetsockopt()
ですTCP_NODELAY
。これにより、プロトコル スタックの Nagle アルゴリズムが無効になり、ソケットの write() または send() が、より直接的にネットワークへの送信にマップされます。より多くのバイトが使用可能になるのを待って、すべてのいつ送信するかを決定する TCP レベル タイマー。注: Nagle をオフにしても、TCP スライディング ウィンドウなどは無効にならないため、いつでも安全に実行できます....しかし、「リアルタイム」プロパティが必要ない場合は、パケットのオーバーヘッドがかなり増加する可能性があります。
さらに、通常の TCP ソケット メカニズムがアプリケーションに適合しない場合は、通常、UDP の使用にフォールバックし、UDP の基本的な送受信プロパティで独自のプロトコル機能を構築する必要があります。これは、プロトコルに特別なニーズがある場合に非常に一般的ですが、これをうまく実行し、比較的単純なアプリケーションを除くすべてのアプリケーションですべてを安定させ、機能的に正しくすることの複雑さを過小評価しないでください。出発点として、TCP の設計機能を徹底的に調査することで、考慮すべき多くの問題が明らかになります。
正しく実装することは不可能ではないにしても、非常に難しいと思います。この文脈での「フラッシュ」の意味は何ですか? ネットワークに送信されたバイト数? 受信者の TCP スタックによって確認されたバイト数? 受信者のユーザー モード アプリに渡されたバイト数? ユーザー モード アプリによって完全に処理されたバイト数?
アプリレベルで行う必要があるようです...
tcpオプションSO_LINGERを設定して特定のタイムアウトを設定し、接続の終了時にすべてのデータが送信されたことを確認する(または送信の失敗を検出する)ためにソケットを閉じることができます。それ以外は、TCPは「ベストエフォート」プロトコルであり、データが実際に宛先に到達することを実際に保証するものではなく(一部の人が信じているように思われるものとは対照的に)、データを配信するために最善を尽くします。正しい順序で、できるだけ早く。
TCP はベスト エフォート型の配信のみを行うため、マシン A からすべてのバイトを送信する動作は、マシン B で受信されたすべてのバイトとは非同期です。TCP/IP プロトコル スタックはもちろん知っていますが、私は何も知りません。 TCP スタックに問い合わせて、送信されたすべてのものが確認されているかどうかを確認する方法。
この問題を処理する最も簡単な方法は、アプリケーション レベルです。バック チャネルとして機能する 2 番目の TCP ソケットを開き、必要な情報を受信したことを示す確認応答をリモート パートナーから送信してもらいます。2 倍の費用がかかりますが、完全に移植可能であり、プログラミング時間を何時間も節約できます。
fsync() を使用します。
sock_fd は socket(..., ...) 呼び出しからの整数ファイル記述子です
fsync(sock_fd);