LPWSPEVENTSELECT
コールバックシグネチャ
INT LPWSPEVENTSELECT(
SOCKET s,
WSAEVENT hEventObject,
INT lNetworkEvents,
INT* lpErrno
);パラメーター
| フィールド | 型 | 説明 | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| s | SOCKET | ソケットを識別するディスクリプターです。 | ||||||||||||||||||||||
| hEventObject | WSAEVENT | 指定された一連のネットワークイベントに関連付けるイベントオブジェクトを識別するハンドルです。 | ||||||||||||||||||||||
| lNetworkEvents | INT | Windows Sockets SPI クライアントが関心を持つネットワークイベントの組み合わせを指定するビットマスクです。次の値のいずれかをビットごとの OR 演算子で組み合わせて構成します。
| ||||||||||||||||||||||
| lpErrno | INT* | エラーコードへのポインターです。詳細については「戻り値」セクションを参照してください。 |
公式ドキュメント
LPWSPEventSelect 関数は、指定された一連のネットワークイベントに関連付けるイベントオブジェクトを指定します。
戻り値
Windows Sockets SPI クライアントによるネットワークイベントと関連するイベントオブジェクトの指定が成功した場合、戻り値は 0 です。それ以外の場合は SOCKET_ERROR が返され、lpErrno に固有のエラー番号が格納されます。
| エラーコード | 意味 |
|---|---|
| ネットワークサブシステムに障害が発生しました。 | |
| 指定されたパラメーターのいずれかが無効であるか、指定されたソケットが無効な状態であることを示します。 | |
| ブロッキング Windows Sockets 呼び出しが進行中であるか、サービスプロバイダーがコールバック関数をまだ処理中です。 | |
| ディスクリプターがソケットではありません。 |
解説(Remarks)
この関数は、選択したネットワークイベント lNetworkEvents に関連付けるイベントオブジェクト hEventObject を指定するために使用します。イベントオブジェクトを指定する対象のソケットは s で識別されます。イベントオブジェクトは、指定されたネットワークイベントのいずれかが発生したときにシグナル状態に設定されます。
LPWSPEventSelect は LPWSPAsyncSelect とよく似た動作をしますが、指定したネットワークイベントが発生したときの動作が異なります。WSPAsyncSelect が Windows Sockets SPI クライアントの指定した Windows メッセージをポストさせるのに対し、LPWSPEventSelect は関連付けられたイベントオブジェクトをシグナル状態にし、そのイベントの発生を内部のネットワークイベントレコードに記録します。Windows Sockets SPI クライアントは LPWSPEnumNetworkEvents を使用して内部のネットワークイベントレコードの内容を取得し、指定したネットワークイベントのうちどれが発生したかを判別できます。
LPWSPEventSelect は、ネットワークの動作とエラーを記録し、LPWSPEnumNetworkEvents を通じて取得できるようにする唯一の関数です。これらの関数がネットワークの動作とエラーをどのように報告するかについては、LPWSPSelect および LPWSPAsyncSelect の説明を参照してください。
この関数は、lNetworkEvents の値にかかわらず、ソケット s を自動的に非ブロッキングモードに設定します。
ソケットに対して LPWSPEventSelect を発行すると、同じソケットに対する以前の LPWSPAsyncSelect または LPWSPEventSelect が取り消され、内部のネットワークイベントレコードがクリアされます。たとえば、読み取りと書き込みの両方のネットワークイベントにイベントオブジェクトを関連付けるには、Windows Sockets SPI クライアントは次のように FD_READ と FD_WRITE の両方を指定して LPWSPEventSelect を呼び出す必要があります。
rc = WSPEventSelect(s, hEventObject, FD_READ | FD_WRITE);
ネットワークイベントごとに異なるイベントオブジェクトを指定することはできません。次のコードは動作しません。2 回目の呼び出しが 1 回目の効果を取り消すため、関連付けは hEventObject2 に関連付けられた FD_WRITE ネットワークイベントだけになります。
// Incorrect example.
rc = WSPEventSelect(s, hEventObject1, FD_READ);
rc = WSPEventSelect(s, hEventObject2, FD_WRITE);
ソケットに対するネットワークイベントの関連付けと選択を取り消すには、lNetworkEvents に 0 を設定します。この場合、hEventObject パラメーターは無視されます。
rc = WSPEventSelect(s, hEventObject, 0);
LPWSPCloseSocket でソケットを閉じた場合も、そのソケットに対して LPWSPEventSelect で指定されたネットワークイベントの関連付けと選択は取り消されます。ただし Windows Sockets SPI クライアントは、イベントオブジェクトを明示的に閉じてリソースを解放するために、引き続き WSACloseEvent を呼び出す必要があります。
LPWSPAccept で受け入れられたソケットは、受け入れに使用したリッスンソケットと同じプロパティを持つため、リッスンソケットに設定された LPWSPEventSelect の関連付けとネットワークイベントの選択は、受け入れられたソケットにも適用されます。たとえば、リッスンソケットが FD_ACCEPT、FD_READ、FD_WRITE について hEventObject との LPWSPEventSelect 関連付けを持つ場合、そのリッスンソケットで受け入れられたソケットにも、同じ hEventObject に関連付けられた FD_ACCEPT、FD_READ、FD_WRITE のネットワークイベントが設定されます。異なる hEventObject やネットワークイベントが必要な場合、Windows Sockets SPI クライアントは、受け入れられたソケットと希望する新しい情報を渡して LPWSPEventSelect を呼び出してください。
ネットワークイベントの発生が正しく記録され、関連付けられたイベントオブジェクトがシグナル状態になった後は、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 の各ネットワークイベントでは、ネットワークイベントの記録とイベントオブジェクトのシグナル通知は レベルトリガー です。つまり、再有効化ルーチンを呼び出した後も該当するネットワーク条件が引き続き成立している場合は、ネットワークイベントが記録され、関連付けられたイベントオブジェクトがシグナル状態になります。これにより Windows Sockets SPI クライアントは、一度に到着するデータ量を気にせずにイベント駆動型で動作できます。次のシーケンスを考えてみます。
- サービスプロバイダーがソケット s で 100 バイトのデータを受信し、FD_READ ネットワークイベントを記録して、関連付けられたイベントオブジェクトをシグナル状態にします。
- Windows Sockets SPI クライアントは 50 バイトを読み取るために
WSPRecv(s, buffptr, 50, 0)を発行します。 - まだ読み取るデータが残っているため、サービスプロバイダーは FD_READ ネットワークイベントを記録し、関連付けられたイベントオブジェクトを再度シグナル状態にします。
このセマンティクスにより、Windows Sockets SPI クライアントは FD_READ ネットワークイベントに応じて利用可能なデータをすべて読み取る必要はありません。むしろ、FD_READ ネットワークイベントごとに 1 回の LPWSPRecv を発行するのが適切です。
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 クライアントが LPWSPEventSelect を呼び出したとき、または再有効化関数が呼び出されたときに、既にネットワークイベントが発生していた場合は、必要に応じてネットワークイベントが記録され、関連付けられたイベントオブジェクトがシグナル状態になります。たとえば、次のシーケンスを考えてみます。
- Windows Sockets SPI クライアントが LPWSPListen を呼び出します。
- 接続要求を受信しますが、まだ受け入れられていません。
- Windows Sockets SPI クライアントは、そのソケットの FD_ACCEPT ネットワークイベントに関心があることを指定して LPWSPEventSelect を呼び出します。サービスプロバイダーは直ちに FD_ACCEPT ネットワークイベントを記録し、関連付けられたイベントオブジェクトをシグナル状態にします。
FD_WRITE ネットワークイベントの扱いは少し異なります。FD_WRITE ネットワークイベントは、ソケットが LPWSPConnect で最初に接続されたとき、または LPWSPAccept で受け入れられたときに記録され、その後は LPWSPSend または LPWSPSendTo が WSAEWOULDBLOCK で失敗した後にバッファー領域が利用可能になったときに記録されます。したがって Windows Sockets SPI クライアントは、最初の FD_WRITE ネットワークイベントの設定時から、送信が WSAEWOULDBLOCK を返すまでの間は送信が可能であると想定できます。そのような失敗の後は、FD_WRITE ネットワークイベントが記録され、関連付けられたイベントオブジェクトがシグナル状態になったときに、再び送信が可能になります。
FD_OOB ネットワークイベントは、ソケットが帯域外データを個別に受信するように構成されている場合にのみ使用されます。ソケットが帯域外データをインラインで受信するように構成されている場合、帯域外 (緊急) データは通常のデータとして扱われるため、Windows Sockets SPI クライアントは FD_OOB ネットワークイベントではなく FD_READ ネットワークイベントに関心を登録する必要があり、FD_READ を受け取ります。Windows Sockets SPI クライアントは、SO_OOBINLINE オプションに対して LPWSPSetSockOpt または LPWSPGetSockOpt を使用して、帯域外データの処理方法を設定または確認できます。
FD_CLOSE ネットワークイベントのエラーコードは、ソケットのクローズが正常 (graceful) だったか、中断 (abortive) だったかを示します。エラーコードが 0 の場合は正常なクローズであり、WSAECONNRESET の場合はソケットの仮想回線がリセットされたことを意味します。これは SOCK_STREAM などのコネクション指向のソケットにのみ適用されます。
FD_CLOSE ネットワークイベントは、ソケットに対応する仮想回線のクローズ通知を受信したときに記録されます。TCP の用語では、接続が FIN WAIT または CLOSE WAIT 状態になったときに FD_CLOSE が記録されることを意味します。これは、リモート側が送信側で LPWSPShutdown を実行したか、LPWSPCloseSocket を実行した結果として発生します。
サービスプロバイダーは、仮想回線のクローズを示すために FD_CLOSE ネットワークイベント のみ を記録してください。その状態を示すために FD_READ ネットワークイベントを記録しては いけません。
FD_QOS または FD_GROUP_QOS ネットワークイベントは、それぞれソケット s、または s が属するソケットグループに関連付けられたフロースペックのいずれかのフィールドに変更があったときに記録されます。この変更は、ソケット s の現在の QOS、または s が属するソケットグループの現在の QOS をそれぞれ取得するために、SIO_GET_QOS または SIO_GET_GROUP_QOS (あるいはその両方) を指定した LPWSPIoctl 関数を通じて、Windows Sockets SPI クライアントが利用できるようにする必要があります。
FD_ROUTING_INTERFACE_CHANGE ネットワークイベントは、WSAIoctl に SIO_ROUTING_INTERFACE_CHANGE を指定して発行した 後 に、そこで指定した宛先に到達するために使用すべきローカルインターフェイスが変更されたときに記録されます。
FD_ADDRESS_LIST_CHANGE ネットワークイベントは、WSAIoctl に SIO_ADDRESS_LIST_CHANGE を指定して発行した 後 に、Windows Sockets SPI クライアントがバインドできるソケットのプロトコルファミリのアドレスリストが変更されたときに記録されます。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)