web-dev-qa-db-ja.com

POSIXソケットをフラッシュする方法はありますか?

POSIXソケットの送信側をリモートエンドまでフラッシュするための標準的な呼び出しはありますか、それともユーザーレベルプロトコルの一部として実装する必要がありますか?通常のヘッダーを調べましたが、何も見つかりませんでした。

36
Gordon Wrigley

Unixドメインソケットの場合、fflush()を使用できますが、おそらくネットワークソケットを意味すると考えています。これらをフラッシュするという概念は実際にはありません。最も近いものは次のとおりです。

  1. セッションの終わりに、shutdown(sock, SHUT_WR)を呼び出してソケットへの書き込みを閉じます。

  2. On TCPソケット、sockopt TCP_NODELAYを使用してNagleアルゴリズムを無効にします。これは、面倒をみているように見えても、一般的には望みを確実に実行できないひどい考えです初期調査。

ユーザープロトコルレベルで「フラッシュ」を要求している問題を処理することは正しいことです。

16
chaos

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のmanページにあるように

TCP_NODELAY ...このオプションを設定すると、保留中の出力が明示的にフラッシュされます...

したがって、おそらくメッセージの後に設定する方が良いでしょうが、他のシステムでどのように機能するかはわかりません

25
fantastory

RFC 1122では、探しているものの名​​前は「プッシュ」です。私はTCP「プッシュ」を実装するAPIを知りませんが。

一部の回答とコメントは、Nagleアルゴリズムを扱っています。それらのほとんどは、Nagleアルゴリズムがすべての送信を遅延させると想定しているようです。この仮定は正しくありません。 Nagleは、前のパケットがまだ確認されていない場合にのみ送信を遅らせます( http://www.unixguide.net/network/socketfaq/2.11.shtml )。

少し簡単にするために:TCPはfirstパケット(パケットの行の)を送信しようとしますimmediately。ただし、タイムアウトに達するか、最初のパケットが確認されるか、どちらか早い方まで、後続のパケットを遅延させます。

1つの解決策は、これらの「後続のパケット」を回避することです。アプリケーションがsend()を複数回呼び出して単一の複合リクエストを送信する場合は、アプリケーションを書き直してください。ユーザー空間でリクエストをアセンブルし、send()を呼び出します。一度。

また、送信バッファにネットワークパケットの最大サイズを満たすのに十分なデータが含まれている場合、Nagleも遅延しません。つまり、Nagleは、send()のバルクデータを小さく分割しても、バルク送信を(実際に)遅延させません。

8
hagello

標準のTCP/IPソケットインターフェイスでは、データを "リモートエンドまでずっと"フラッシュし、実際に確認されたことを確認する方法はありません。

一般的に、プロトコルでデータの「リアルタイム」転送が必要な場合、一般的に行うべき最善の方法は、_TCP_NODELAY_のsetsockopt()を設定することです。これにより、プロトコルスタックのNagleアルゴリズムが無効になり、ソケットでwrite()またはsend()がネットワークに送信するためにより直接的にマップされます.... TCP送信するタイミングを決定するレベルタイマー。注:Nagleをオフにしても、TCPスライディングウィンドウなどは無効にならないため、常に安全です。 ...しかし、「リアルタイム」プロパティが必要でない場合、パケットのオーバーヘッドはかなり大きくなる可能性があります。

それ以外に、通常のTCPソケットメカニズムがアプリケーションに適合しない場合は、一般にUDPを使用し、UDPの基本的な送受信プロパティで独自のプロトコル機能を構築する必要がありますこれは、プロトコルに特別なニーズがある場合に非常に一般的ですが、比較的単純なアプリケーションを除き、これをうまく行い、すべてを安定して機能的に正しくする複雑さを過小評価しないでください。考慮する必要のある多くの問題に光を当てます。

7
Tall Jeff

TCPはベストエフォート型の配信のみを提供するため、すべてのバイトがマシンAを離れるという行為は、すべてがマシンBで受信されたものと非同期です。TCP/ IPプロトコルスタックはもちろん知っていますが、私は知りませんTCPスタックに問い合わせて、送信されたすべてが確認されたかどうかを確認する方法。

質問を処理する最も簡単な方法は、アプリケーションレベルでです。 2番目のTCPソケットを開いて、バックチャンネルとして機能し、必要な情報を受信したという確認をリモートパートナーに送信します。コストは2倍になりますが、完全にポータブルで節​​約できますプログラミングに何時間もかかります。

0
Norman Ramsey

TcpオプションSO_LINGERを設定して特定のタイムアウトを設定し、接続を閉じたときにすべてのデータが送信されたことを確認する(または失敗したことを検出する)ためにソケットを閉じます。それ以外は、TCPは「ベストエフォート」プロトコルであり、データが実際に宛先に到達することを保証するものではありません(一部の人は信じているように思われます)正しい順序で、できるだけ早く配信されるように最善を尽くすだけです。

0
user1402866