LPWSPASYNCSELECT
コールバックシグネチャ
INT LPWSPASYNCSELECT(
SOCKET s,
HWND hWnd,
DWORD wMsg,
INT lEvent,
INT* lpErrno
);パラメーター
| フィールド | 型 | 説明 | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| s | SOCKET | イベント通知を必要とするソケットを識別する記述子。 | ||||||||||||||||||||||
| hWnd | HWND | ネットワークイベントが発生したときにメッセージを受け取るウィンドウを識別するハンドル。 | ||||||||||||||||||||||
| wMsg | DWORD | ネットワークイベントが発生したときに送信されるメッセージ。 | ||||||||||||||||||||||
| lEvent | INT | Windows Sockets サービスプロバイダーインターフェイス (SPI) クライアントが関心を持つネットワークイベントの組み合わせを指定するビットマスク。次の値のいずれかをビットごとの OR 演算子で組み合わせて構築します。
| ||||||||||||||||||||||
| lpErrno | INT* | エラーコードへのポインター。詳細については、戻り値 セクションを参照してください。 |
公式ドキュメント
LPWSPAsyncSelect 関数は、ソケットに対するネットワークイベントの Windows メッセージベースのイベント通知を要求します。
戻り値
Windows Sockets SPI クライアントによるネットワークイベントセットへの関心の宣言が成功した場合、戻り値は 0 です。それ以外の場合は SOCKET_ERROR が返され、lpErrno に固有のエラーコードが格納されます。
| エラーコード | 意味 |
|---|---|
| ネットワークサブシステムが失敗しました。 | |
| 指定されたパラメーターの 1 つが無効であることを示します。たとえば、ウィンドウハンドルが既存のウィンドウを参照していない、または指定されたソケットが無効な状態にある場合です。 | |
| ブロッキング Windows Sockets 呼び出しが進行中であるか、サービスプロバイダーがコールバック関数を処理中です。 | |
| 記述子がソケットではありません。 |
アプリケーションのウィンドウがメッセージを受け取ったときに設定される可能性のある追加のエラーコード (メッセージ内の lParam の上位ワードに格納) については、解説 を参照してください。
解説(Remarks)
この関数は、lEvent 引数で指定されたネットワークイベントのいずれかをサービスプロバイダーが検出したときに、クライアントのウィンドウ hWnd へ Windows メッセージを送信するようサービスプロバイダーに要求するために使用します。サービスプロバイダーは、メッセージをポストするために WPUPostMessage 関数を使用する必要があります。送信されるメッセージは wMsg パラメーターで指定します。通知が必要なソケットは s で識別します。
この関数は、lEvent の値にかかわらず、ソケット s を自動的に非ブロッキングモードに設定します。ソケットをブロッキングモードに戻す方法については、LPWSPIoctl を参照してください。
あるソケットに対して LPWSPAsyncSelect を呼び出すと、同じソケットに対する以前の LPWSPAsyncSelect または LPWSPEventSelect は取り消されます。たとえば、読み取りと書き込みの両方の通知を受け取るには、Windows Sockets SPI クライアントは次のように FD_READ と FD_WRITE の両方を指定して LPWSPAsyncSelect を呼び出す必要があります。
rc = WSPAsyncSelect(s, hWnd, wMsg, FD_READ | FD_WRITE, &error);
イベントごとに異なるメッセージを指定することはできません。次のコードは動作しません。2 回目の呼び出しが 1 回目の効果を取り消すため、有効な関連付けは wMsg2 に関連付けられた FD_WRITE イベントのみになります。
// 誤った例。
rc = WSPAsyncSelect(s, hWnd, wMsg1, FD_READ, &error);
rc = WSPAsyncSelect(s, hWnd, wMsg2, FD_WRITE, &error);
すべての通知を取り消す (つまり、そのソケットのネットワークイベントに関連するメッセージをサービスプロバイダーがこれ以上送信しないようにする) には、lEvent に 0 を設定します。
rc = WSPAsyncSelect(s, hWnd, 0, 0, &error);
LPWSPAccept で受け入れられたソケットは、受け入れに使用したリッスンソケットと同じプロパティを持つため、リッスンソケットに設定された LPWSPAsyncSelect イベントは、受け入れられたソケットにも適用されます。たとえば、リッスンソケットに FD_ACCEPT、FD_READ、FD_WRITE の LPWSPAsyncSelect イベントが設定されている場合、そのリッスンソケットで受け入れられたソケットも、メッセージに使用される同じ wMsg 値で FD_ACCEPT、FD_READ、FD_WRITE の各イベントを持ちます。異なる wMsg やイベントが必要な場合、Windows Sockets SPI クライアントは、受け入れられたソケットと必要な新しい情報を渡して LPWSPAsyncSelect を呼び出す必要があります。
指定されたソケット s で指定済みのネットワークイベントのいずれかが発生すると、サービスプロバイダーは WPUPostMessage を使用して、Windows Sockets SPI クライアントのウィンドウ hWnd にメッセージ wMsg を送信します。ポストされたメッセージでは、wParam 引数がネットワークイベントの発生したソケットを識別します。lParam の下位ワードは、発生したネットワークイベントを指定します。示される可能性のあるネットワークイベントコードは次のとおりです。
| 値 | 意味 |
|---|---|
| FD_READ | ソケット s が読み取り可能です |
| FD_WRITE | ソケット s が書き込み可能です |
| FD_OOB | ソケット s で帯域外データを読み取れます |
| FD_ACCEPT | ソケット s が新しい着信接続を受け入れ可能です |
| FD_CONNECT | ソケット s で開始された接続が完了しました |
| FD_CLOSE | ソケット s で識別される接続がクローズされました |
| FD_QOS | ソケット s に関連付けられたサービス品質が変更されました |
| FD_GROUP_QOS | ソケットグループでの将来の使用のために予約: ソケット s が属するソケットグループに関連付けられたサービス品質が変更されました |
| FD_ROUTING_INTERFACE_CHANGE | 指定された宛先への送信に使用すべきローカルインターフェイスが変更されました |
| FD_ADDRESS_LIST_CHANGE | Windows Sockets SPI クライアントがバインドできる、ソケットのプロトコルファミリのアドレスのリストが変更されました |
lParam の上位ワードにはエラーコードが格納されます (WSAGETSELECTERROR マクロを使用して取り出せます)。エラーコードは、ws2spi.h で定義されている任意のエラーになり得ます。各ネットワークイベントで発生し得るエラーコードを次の表に示します。
イベント: FD_CONNECT
| エラーコード | 意味 |
|---|---|
| 指定されたファミリのアドレスは、このソケットでは使用できません。 | |
| 接続の試行が拒否されました。 | |
| 現時点では、このホストからネットワークに到達できません。 | |
| namelen パラメーターが無効です。 | |
| ソケットは既にアドレスにバインドされています。 | |
| ソケットは既に接続されています。 | |
| 使用可能なファイル記述子がこれ以上ありません。 | |
| 使用可能なバッファー領域がありません。ソケットを接続できません。 | |
| ソケットは接続されていません。 | |
| 接続の試行がタイムアウトし、接続は確立されませんでした。 |
イベント: FD_CLOSE
| エラーコード | 意味 |
|---|---|
| ネットワークサブシステムが失敗しました。 | |
| リモート側によって接続がリセットされました。 | |
| タイムアウトまたはその他の障害により接続が終了しました。 |
イベント...: FD_ACCEPT, FD_ADDRESS_LIST_CHANGE, FD_GROUP_QOS, FD_OOB, FD_QOS, FD_READ, FD_WRITE
| エラーコード | 意味 |
|---|---|
| ネットワークサブシステムが失敗しました。 |
イベント: FD_ROUTING_INTERFACE_CHANGE
| エラーコード | 意味 |
|---|---|
| 指定された宛先に到達できなくなりました。 | |
| ネットワークサブシステムが失敗しました。 |
LPWSPAsyncSelect は複数のイベントに関心を持って呼び出すことができますが、サービスプロバイダーはどのイベントについても同じ Windows メッセージを発行します。
Windows Sockets 2 プロバイダーは、特定のネットワークイベントのメッセージを Windows Sockets SPI クライアントに絶えず送りつけるべきではありません。特定のイベントの通知を Windows Sockets SPI クライアントのウィンドウに正常にポストした後は、そのネットワークイベントの通知を暗黙的に再度有効にする関数を Windows Sockets SPI クライアントが呼び出すまで、そのネットワークイベントに関するメッセージがクライアントのウィンドウにこれ以上ポストされることはありません。
| ネットワークイベント | 再度有効にする関数 |
|---|---|
| FD_READ | LPWSPRecv または LPWSPRecvFrom |
| FD_WRITE | LPWSPSend または LPWSPSendTo |
| FD_OOB | LPWSPRecv または LPWSPRecvFrom |
| FD_ACCEPT | LPWSPAccept。ただし、返されたエラーコードが WSATRY_AGAIN で、条件関数が CF_DEFER を返したことを示す場合を除く |
| FD_CONNECT | なし |
| FD_CLOSE | なし |
| FD_QOS | SIO_GET_QOS を指定した LPWSPIoctl |
| FD_GROUP_QOS | ソケットグループでの将来の使用のために予約: SIO_GET_GROUP_QOS を指定した LPWSPIoctl |
| FD_ROUTING_INTERFACE_CHANGE | SIO_ROUTING_INTERFACE_CHANGE コマンドを指定した LPWSPIoctl |
| FD_ADDRESS_LIST_CHANGE | SIO_ADDRESS_LIST_CHANGE コマンドを指定した LPWSPIoctl |
再度有効にするルーチンの呼び出しは、失敗した場合でも、該当するイベントのメッセージのポストを再度有効にします。
FD_READ、FD_OOB、FD_ACCEPT の各イベントでは、メッセージのポストは レベルトリガー です。つまり、再度有効にするルーチンが呼び出され、その呼び出し後も該当する条件が満たされている場合、LPWSPAsyncSelect メッセージが Windows Sockets SPI クライアントにポストされます。
FD_QOS と FD_GROUP_QOS のイベントは エッジトリガー と見なされます。QOS の変更が発生すると、メッセージはちょうど 1 回だけポストされます。プロバイダーがさらなる QOS の変更を検出するか、Windows Sockets SPI クライアントがそのソケットの QOS を再ネゴシエートするまで、それ以上のメッセージは送られません。
FD_ROUTING_INTERFACE_CHANGE と FD_ADDRESS_LIST_CHANGE のイベントも同様に エッジトリガー と見なされます。Windows Sockets SPI クライアントが WSAIoctl をそれぞれ SIO_ROUTING_INTERFACE_CHANGE または SIO_ADDRESS_LIST_CHANGE で発行して通知を要求した後に変更が発生すると、メッセージはちょうど 1 回だけポストされます。Windows Sockets SPI クライアントが IOCTL を再発行し、かつ その IOCTL の発行後に別の変更が検出されるまで、それ以上のメッセージは送られません。
Windows Sockets SPI クライアントが LPWSPAsyncSelect を呼び出したとき、または再度有効にする関数が呼び出されたときに、いずれかのイベントが既に発生していた場合は、適宜メッセージがポストされます。たとえば、次のような順序を考えます。
- Windows Sockets SPI クライアントが LPWSPListen を呼び出します。
- 接続要求を受信しますが、まだ受け入れられていません。
- Windows Sockets SPI クライアントが、そのソケットの FD_ACCEPT メッセージを受け取りたいことを指定して LPWSPAsyncSelect を呼び出します。イベントの永続性により、WinSock サービスプロバイダーは直ちに FD_ACCEPT メッセージをポストします。
FD_WRITE イベントの扱いは少し異なります。FD_WRITE メッセージは、ソケットが LPWSPConnect で最初に接続されたとき (FD_CONNECT も登録されている場合はその後)、または LPWSPAccept で受け入れられたとき、さらにその後 LPWSPSend または LPWSPSendTo が WSAEWOULDBLOCK で失敗してバッファー領域が使用可能になったときにポストされます。したがって、Windows Sockets SPI クライアントは、最初の FD_WRITE メッセージから送信が WSAEWOULDBLOCK を返すまでの間は送信が可能であると想定できます。そのような失敗の後、再び送信が可能になると、Windows Sockets SPI クライアントに FD_WRITE メッセージで通知されます。
FD_OOB イベントは、ソケットが帯域外データを別個に受信するように構成されている場合にのみ使用されます。ソケットが帯域外データをインラインで受信するように構成されている場合、帯域外 (緊急) データは通常のデータとして扱われ、Windows Sockets SPI クライアントは FD_OOB イベントではなく FD_READ イベントに関心を登録する必要があります。
FD_CLOSE メッセージのエラーコードは、ソケットのクローズが正常だったか異常終了だったかを示します。エラーコードが 0 の場合、クローズは正常に行われました。エラーコードが WSAECONNRESET の場合、ソケットの仮想回線がリセットされました。これは SOCK_STREAM などのコネクション指向ソケットにのみ適用されます。
FD_CLOSE メッセージは、ソケットに対応する仮想回線のクローズ通知を受信したときにポストされます。TCP の用語では、これは接続が TIME WAIT または CLOSE WAIT 状態になったときに FD_CLOSE がポストされることを意味します。これは、リモート端が送信側で LPWSPShutdown を実行するか、LPWSPCloseSocket を実行した結果として発生します。FD_CLOSE がソケットからすべてのデータが読み取られた後にのみポストされるのは正しい動作です。
正常なクローズの場合、サービスプロバイダーは、受信済みのデータがすべて読み取られた後にのみ、仮想回線のクローズを示す FD_CLOSE メッセージを送信する必要があります。この状態を示すために FD_READ メッセージを送信してはなりません。
FD_QOS または FD_GROUP_QOS メッセージは、それぞれソケット s、または s が属するソケットグループに関連付けられたフロー仕様のいずれかのフィールドに変更があったときにポストされます。サービスプロバイダーは、SIO_GET_QOS や SIO_GET_GROUP_QOS を指定した LPWSPIoctl を通じてクライアントが利用できる QOS 情報を更新する必要があります。
FD_ROUTING_INTERFACE_CHANGE メッセージは、SIO_ROUTING_INTERFACE_CHANGE を指定した LPWSPIoctl で指定された宛先に到達するために使用すべきローカルインターフェイスが、その IOCTL の発行 後 に変更されたときにポストされます。
FD_ADDRESS_LIST_CHANGE メッセージは、SIO_ADDRESS_LIST_CHANGE を指定した LPWSPIoctl の発行 後 に、Windows Sockets SPI クライアントがバインドできるアドレスのリストが変更されたときにポストされます。
各非同期通知メッセージのイベントと条件の概要を次に示します。
- LPWSPAsyncSelect が呼び出されたときに、現在受信可能なデータがある場合。
- データが到着したときに、FD_READ がまだポストされていない場合。
- LPWSPRecv または LPWSPRecvFrom が (MSG_PEEK の有無にかかわらず) 呼び出された後、まだ受信可能なデータがある場合。
LPWSPSetSockOpt の SO_OOBINLINE が有効な場合、上記の各ケースにおける データ には、通常のデータと帯域外 (OOB) データの両方が含まれます。
- LPWSPAsyncSelect が呼び出されたときに、LPWSPSend または LPWSPSendTo が可能な場合。
- LPWSPConnect または LPWSPAccept が呼び出された後、接続が確立されたとき。
- LPWSPSend または LPWSPSendTo が WSAEWOULDBLOCK で失敗した後、LPWSPSend または LPWSPSendTo が成功する見込みになったとき。
- コネクションレスソケットで LPWSPBind を実行した後。このとき FD_WRITE が発生する場合と発生しない場合があります (実装依存)。いずれの場合も、コネクションレスソケットは LPWSPBind の直後から常に書き込み可能です。
FD_OOB (LPWSPSetSockOpt の SO_OOBINLINE が無効 (既定) の場合にのみ有効)
- LPWSPAsyncSelect が呼び出されたときに、MSG_OOB フラグで受信可能な OOB データが現在ある場合。
- OOB データが到着したときに、FD_OOB がまだポストされていない場合。
- MSG_OOB フラグの有無にかかわらず LPWSPRecv または LPWSPRecvFrom が呼び出された後、まだ受信可能な OOB データがある場合。
- LPWSPAsyncSelect が呼び出されたときに、受け入れ可能な接続要求が現在ある場合。
- 接続要求が到着したときに、FD_ACCEPT がまだポストされていない場合。
- LPWSPAccept が呼び出された後、受け入れ可能な別の接続要求がある場合。
- LPWSPAsyncSelect が呼び出されたときに、接続が現在確立されている場合。
- LPWSPConnect が呼び出された後、接続が確立されたとき (データグラムソケットで一般的なように LPWSPConnect が直ちに成功した場合や、直ちに失敗した場合も含む)。
- WSPJoinLeaf が呼び出された後、join 操作が完了したとき。
- 非ブロッキングのコネクション指向ソケットで connect、WSAConnect、または WSPJoinLeaf が呼び出された後。最初の操作は WSAEWOULDBLOCK という固有のエラーで戻りますが、ネットワーク操作は続行されます。最終的に操作が成功するかどうかにかかわらず、結果が確定した時点で FD_CONNECT が発生します。クライアントはエラーコードを確認して、結果が成功か失敗かを判断する必要があります。
FD_CLOSE (コネクション指向ソケット (SOCK_STREAM など) でのみ有効)
- LPWSPAsyncSelect が呼び出されたときに、ソケットの接続が既にクローズされている場合。
- リモートシステムが正常なクローズを開始した後、現在受信可能なデータがないとき (リモートシステムが正常なクローズを開始した時点で、受信済みで読み取り待ちのデータがある場合、保留中のデータがすべて読み取られるまで FD_CLOSE は配信されません)。
- ローカルシステムが LPWSPShutdown で正常なクローズを開始し、リモートシステムが データ終端 通知 (TCP FIN など) で応答した後、現在受信可能なデータがないとき。
- リモートシステムが接続を中止したとき (TCP RST を送信した場合など)。このとき lParam には WSAECONNRESET エラー値が格納されます。
LPWSPCloseSocket が呼び出された後に FD_CLOSE がポストされることはありません。
FD_QOS
- LPWSPAsyncSelect が呼び出されたときに、ソケットに関連付けられた QOS が変更されている場合。
- SIO_GET_QOS を指定した LPWSPIoctl が呼び出された後、QOS が変更されたとき。
FD_GROUP_QOS
ソケットグループでの将来の使用のために予約されています:
- LPWSPAsyncSelect が呼び出されたときに、ソケットに関連付けられたグループ QOS が変更されている場合。
- SIO_GET_GROUP_QOS を指定した LPWSPIoctl が呼び出された後、グループ QOS が変更されたとき。
FD_ROUTING_INTERFACE_CHANGE
- SIO_ROUTING_INTERFACE_CHANGE を指定した LPWSPIoctl が呼び出された後、IOCTL で指定された宛先に到達するために使用すべきローカルインターフェイスが変更されたとき。
FD_ADDRESS_LIST_CHANGE
- SIO_ADDRESS_LIST_CHANGE を指定した LPWSPIoctl が呼び出された後、Windows Sockets SPI クライアントがバインドできるローカルアドレスのリストが変更されたとき。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)