私は I/O Completion Ports を何年も前から聞いていましたが、一度も使用したことがないと言って前に付けておきます。私のバックグラウンドは主にselect
、poll
、epoll
、およびWSAEventSelect
ですWaitForMulitpleObjects
。次のテキストの I/O Completion Ports について根本的な誤解がある場合は、訂正してください。
仕事中のプロジェクトの一環として、クライアントがプラグインに接続し、TCP 経由でシミュレーションとの間でデータを送受信できるようにするプラグイン (DLL) をシミュレーションに開発する任務を負っています。プラグインはサーバーとして機能します。シミュレーションは、別の (イーサネットではない) インターフェイスの通信チャネルをシミュレートします。この特定のアプリケーションでは、チャネルごとに 1 つのソケットを持つことが理にかなっています。いくつのクライアントが存在するか、または各クライアントによっていくつのチャネル (ソケット) が開かれるかはわかりません。ただし、64 を超える可能性が十分にあり、それが異常に多くないこと、おそらくせいぜい 1000 未満であることはわかっています。
シミュレーションの重要な側面は、関数が呼び出されたときにのみプラグインが動作できることですtest_cycle
。各テスト サイクル中に、次のことを行う必要があります。
- クライアントからの新しい接続を受け入れる
- ソケットからデータを受信し、シミュレーションに転送します
- シミュレーションからデータを受け取り、クライアントに転送します
64 を超えるソケットが存在する可能性があるため、(簡単に) WSAEventSelect
andWSAWaitForMultipleEvents
を使用して、ソケットを読み取れるかどうか、またはクライアントが正常に接続を終了したかどうかを確認することはできません。
そのため、これを行うことができる他の 2 つの方法を考えました。
各ソケットをノンブロッキングにします。が呼び出されるたび
test_cycle
に、ソケットごとに最大量のデータを受信しようとして、すべてのソケットをループします。I/O Completion Port を使用して、ソケットから非同期受信を発行します。で、タイムアウトが示される ( ?)まで、パラメーターを に設定して呼び出しを
test_cycle
繰り返します。受信が発生した場合は、テスト サイクルが終了するまで次の受信呼び出しを延期します。これにより、クライアントがサーバーにメッセージをスパム送信しても、無期限にループすることはありません(うまくいけば)。GetQueuedCompletionStatus
dwMilliseconds
0
WAIT_TIMEOUT
test_cycle
シミュレーションへのインターフェイスはスレッドセーフではなく、データをシミュレーションに転送するために行う処理作業はほとんどないため、I/O 完了ポートにワーカー スレッドを使用するメリットはないと思います。 、ロックを実行してシミュレーション API を呼び出すだけです。ただし、各ソケットをポーリングする必要がないため、パフォーマンスが向上する場合があります。
この規模のアプリケーションでは、最大ソケット数が約 1000 未満、通常は 100 未満ですが、I/O Completion Ports を使用することで複雑さが増すことに、実際にメリットはあるのでしょうか?