1

10 (またはそれ以上) の異なるクライアントからの接続を受け入れることができるサーバー プログラムがあるとします。クライアントはランダムにデータを送信し、サーバーが受信しますが、更新ごとに少なくとも 1 つのクライアントがデータを送信することは確実です。サーバーは、他の処理を行う必要があるため、情報の到着を待つことができません。非同期ソケットを使用する以外に、次の 2 つのオプションがあります。

  1. すべてのソケットをノンブロッキングにします。ループ内recv()で各ソケットを呼び出し、WSAEWOULDBLOCK利用可能なデータがない場合は失敗させ、たまたまデータを取得した場合はそれを保持します。

  2. ソケットはブロッキングのままにします。すべてのソケットを に追加し、FD_SETを呼び出しますselect()。戻り値が 0 以外の場合 (ほとんどの場合)、すべてのソケットをループして、適切な数の読み取り可能なソケットを見つけ、読み取り可能なソケットFD_ISSET()のみを呼び出しますrecv()

最初のオプションは、関数へのより多くの呼び出しを作成しrecv()ます。FD_SET2 番目の方法は、すべてのandFD_ISSETループが原因で、プログラミングの観点からはより大きな問題になります。

どの方法 (または別の方法) が優先されますか? recv()呼び出しの面倒な価値があるノンブロッキングソケットで失敗することによるオーバーヘッドを回避していますselect()か?

私は両方の方法を理解しており、両方を試して成功したと思いますが、一方の方法がより良いまたは最適であると見なされるかどうかはわかりません。

4

2 に答える 2

2

代わりにオーバーラップ IOを使用することをお勧めします。その後WSARecv()、 を開始し、操作の完了時に呼び出されるコールバック関数を提供できます。さらに、プログラムがアラート可能な待機状態にある場合にのみ呼び出されるため、スレッド化されたアプリケーションの場合のようにロックについて心配する必要はありません (メイン スレッドで実行すると仮定します)。

ただし、このようなアラート可能な待機状態に頻繁に入る必要があることに注意してください。これが UI スレッドである場合MsgWaitForMultipleObjectsEx()は、メッセージ ループでMWMO_ALERTABLEフラグを使用してください。これにより、コールバックを実行する機会が与えられます。非 UI スレッドでは、アラート可能な待機状態にする待機関数を定期的に呼び出します。

を呼び出さない独自のメッセージ ループがあるため、モーダル ダイアログは通常、警告可能な待機状態にはならないことにも注意してくださいMsgWaitForMultipleObjectsEx()。ダイアログ ボックスを表示するときにネットワーク IO を処理する必要がある場合は、すべてのネットワーク IO を専用スレッドで実行します。このスレッドは定期的にアラート可能な待機状態に入ります。

何らかの理由でオーバーラップ IO を使用できない場合は、必ずブロッキングを使用してselect()ください。無限ループでそのようなノンブロッキングを使用recv()することは、許しがたい CPU 時間の浪費です。ただし、ソケットをノンブロッキング モードにしてください。そうしないと、1 バイトが到着したときに 2 バイトを読み取ろうとすると、予期せずブロックしてしまう可能性があります。

ライブラリを使用して、厄介な詳細を抽象化することを検討することもできます。たとえば、libeventまたはboost::asio

于 2009-10-06T15:32:34.560 に答える
1

IOは、接続ごとに1つのスレッドで完全にブロックする必要があります。この場合、イベントループは基本的にOSスケジューラであるか、IOは完全に非ブロックである必要があります。この場合、複数オブジェクトベースのイベントループの選択/待機がアプリケーションに含まれます。

すべての中間バリアントは、保守性が低く、エラーが発生しやすいわけではありません。

完全にノンブロッキングのアプローチは、同時接続の量が増え、スレッドコンテキストスイッチのオーバーヘッドがない場合にはるかに拡張性が高いため、同時接続の数が固定されていない場合に適しています。このアプローチは、完全にブロックする場合に比べて、実装が複雑になります。

完全に非ブロッキングIOの場合、アプリケーションのコアは複数オブジェクトベースのイベントループの選択/待機であり、すべてのソケットは非ブロッキングモードであり、すべての読み取り/書き込みは通常、イベントループスレッド内から実行されます(最高のパフォーマンスの書き込みは最初に書き込みを要求しているスレッドから直接試行されました)

于 2010-05-10T14:42:30.183 に答える