6

メッセージウィンドウとWSAAsyncSelectを使用しています。1つのメッセージウィンドウで複数のソケット(クライアント)を追跡するにはどうすればよいですか?

4

2 に答える 2

15

Windows はソケット操作のいくつかのモードをサポートしており、どのモードを使用しているかを明確にする必要があります。

  • ブロッキングソケット。送信および受信ブロック。
  • ノンブロッキング ソケット: send と recv は E_WOULDBLOCK を返し、select() はどのソケットが準備できているかを判断するために使用されます。
  • 非同期ソケット: WSAAsyncSelect - ソケットはイベント通知を HWND に投稿します。
  • EventSockets: WSAEventSelect - ソケット シグナル イベント。
  • オーバーラップされたソケット: WSASend と WSARecv は、OVERLAPPED 構造体を渡すことによってソケットで使用されます。オーバーラップ ソケットは IOCompletionPorts と組み合わせることができ、最高のスケーラビリティを提供します。

利便性の面では、非同期ソケットは単純であり、MFC CAsyncSocket クラスでサポートされています。

WaitForMultipleObjects に渡すことができるオブジェクトの最大数は 64 であるため、イベント ソケットの使用には注意が必要です。

IO CompletionPorts を使用したオーバーラップ ソケットは、ソケットを処理する最もスケーラブルな方法であり、Windows ベースのサーバーを数万のソケットに拡張できます。


私の経験では、非同期ソケットを使用する場合、次のことが頭に浮かびます。

  • ウィンドウ メッセージを介して FD イベントを処理すると、「たくさんの」ソケットを処理できますが、すべてのイベント処理が 1 つのスレッドで行われ、メッセージ キューを介してシリアル化されるため、パフォーマンスが低下し始めます。 GUI アプリ。

  • 多くのソケットと同じスレッドで GUI ウィンドウまたはタイマーをホストしている場合: WM_TIMER および WM_PAINT メッセージは優先度が低く、メッセージ キューが空の場合にのみ生成されます。したがって、ソケットが非常にビジーであると、GUI 描画や SetTimer ベースのタイミングが失敗する可能性があります。

  • GUI をホストすることでこれらの問題が解決する場合は、ソケットを処理する専用のワーカー スレッドを作成します。ワーカー スレッドにメッセージ ループがある場合、スレッド間通信にメッセージ キューを使用できます。WM_APP メッセージをスレッドにポストするだけです。

  • FD コールバックをソケット オブジェクトにマップする最も簡単な方法は、メッセージを受信する HWND ごとに SocketObjects の配列を作成し、WASAsyncSelect を呼び出すたびに WM_USER+index をメッセージ ID として使用することです。次に、WM_USER から WM_USER+(配列サイズ) の範囲のメッセージを受信すると、対応する状態オブジェクトをすばやく抽出できます。WM_USER は 0x400 で、WM_APP は 0x8000 であるため、この方法を使用して、メッセージ ウィンドウごとに最大 31744 ソケットのインデックスを作成できます。

  • 静的スコープ配列を使用しないでください。複数のスレッドでソケットを作成する場合があるため、配列をウィンドウに関連付ける必要があります。各スレッドには、独自のメッセージ ループとメッセージ ウィンドウが必要です。

  • HWND_MESSAGE はあなたの友達です

于 2011-02-18T05:34:43.107 に答える
0

wParam送信するように指示するウィンドウ メッセージのパラメーターは、メッセージWSAAsyncSelect()をトリガーしたソケットを指定します。これはWSAAsyncSelect() ドキュメントに明確に記載されています:

指定されたネットワーク イベントの 1 つが指定されたソケット s で発生すると、アプリケーション ウィンドウ hWnd はメッセージ wMsg を受け取ります。wParam パラメータは、ネットワーク イベントが発生したソケットを識別します。lParam の下位ワードは、発生したネットワーク イベントを指定します。lParam の上位ワードにはエラー コードが含まれます。エラー コードは、Winsock2.h で定義されている任意のエラーです。

于 2011-02-18T19:34:41.833 に答える