WSAEventSelect 関数 (winsock2.h)
WSAEventSelect 関数は、指定したネットワーク イベントのセットに関連付けるイベント オブジェクトFD_XXX指定します。
構文
int WSAAPI WSAEventSelect(
[in] SOCKET s,
[in] WSAEVENT hEventObject,
[in] long lNetworkEvents
);
パラメーター
[in] s
ソケットを識別する記述子。
[in] hEventObject
指定したネットワーク イベントのセットに関連付けられるイベント オブジェクトを識別FD_XXXハンドル。
[in] lNetworkEvents
アプリケーションが関心を持つFD_XXXネットワーク イベントの組み合わせを指定するビットマスク。
戻り値
ネットワーク イベントと関連するイベント オブジェクトのアプリケーションの指定が成功した場合、戻り値は 0 です。 それ以外の場合は、SOCKET_ERROR値が返され、 WSAGetLastError を呼び出すことによって特定のエラー番号を取得できます。
select 関数と WSAAsyncSelect 関数の場合と同様に、WSAEventSelect は、データ転送操作 (送信または recv) を即時成功を期待して発行できるタイミングを判断するために頻繁に使用されます。 それでも、堅牢なアプリケーションは、イベント オブジェクトが設定され、 WSAEWOULDBLOCK を直ちに返す Windows ソケット呼び出しを発行する可能性に備えて準備する必要があります。 たとえば、次の一連の操作を実行できます。
- データはソケット に到着します。Windows ソケットは、 WSAEventSelect イベント オブジェクトを設定します。
- アプリケーションは他の処理を行います。
- 処理中に、アプリケーションは ioctlsocket(s, FIONREAD...) を発行し、読み取る準備ができているデータがあることを確認します。
- アプリケーションは、データを読み取るために recv(s,...) を発行します。
- アプリケーションは最終的に WSAEventSelect で指定されたイベント オブジェクトを待機します。これは、データを読み取る準備ができていることを示す直ちにを返します。
- アプリケーションが recv(s,...) を発行します。これはエラー WSAEWOULDBLOCK で失敗します。
ネットワーク イベント | 関数の再有効化 |
---|---|
|
recv、recvfrom、WSARecv、WSARecvEx、または WSARecvFrom 関数。 |
|
send、sendto、WSASend、または WSASendTo 関数。 |
|
recv、recvfrom、WSARecv、WSARecvEx、または WSARecvFrom 関数。 |
|
返されるエラー コードが条件関数からCF_DEFER返されたことを示すWSATRY_AGAINでない限り、 accept、 AcceptEx、または WSAAccept 関数。 |
|
[なし] : |
|
[なし] : |
|
コマンド SIO_GET_QOSを含む WSAIoctl 関数。 |
|
予約済み。 |
|
コマンド SIO_ROUTING_INTERFACE_CHANGEを使用した WSAIoctl 関数。 |
|
コマンド SIO_ADDRESS_LIST_CHANGEを使用した WSAIoctl 関数。 |
再有効化ルーチンを呼び出すと、失敗したルーチンであっても、関連するネットワーク イベントおよびイベント オブジェクトの記録とシグナリングが再び有効になります。
ネットワーク イベントのFD_READ、FD_OOB、FD_ACCEPTの場合、ネットワーク イベントの記録とイベント オブジェクトのシグナリングはレベル によってトリガーされます。 つまり、再有効化ルーチンが呼び出され、関連するネットワーク条件が呼び出し後も有効な場合は、ネットワーク イベントが記録され、関連付けられているイベント オブジェクトが設定されます。 これにより、アプリケーションはイベント ドリブンになり、一度に到着するデータの量には関係ありません。 次の例について考えてみます。
- トランスポート プロバイダーは、ソケット s で 100 バイトのデータを受信し、WS2_32.DLL FD_READネットワーク イベントを記録し、関連付けられているイベント オブジェクトを設定します。
- アプリケーションは recv(s, buffptr, 50, 0) を発行して 50 バイトを読み取ります。
- トランスポート プロバイダーは、WS2_32.DLL にFD_READネットワーク イベントを記録し、読み取るデータが残っているため、関連付けられているイベント オブジェクトを再び設定します。
FD_QOS イベントはエッジ トリガーと見なされます。 サービス品質の変更が発生すると、メッセージが 1 回だけ投稿されます。 プロバイダーがサービスの品質のさらなる変更を検出するか、アプリケーションがソケットのサービス品質を再ネゴシエーションするまで、それ以上のメッセージは今後は表示されません。
FD_ROUTING_INTERFACE_CHANGEイベントとFD_ADDRESS_LIST_CHANGE イベントもエッジ トリガーと見なされます。 アプリケーションが通知を要求した後に、SIO_ROUTING_INTERFACE_CHANGEまたはSIO_ADDRESS_LIST_CHANGEを使用して WSAIoctl を発行した後に変更が発生すると、メッセージは 1 回だけ投稿されます。 アプリケーションが IOCTL を再発行し、IOCTL が発行されてから別の変更が検出されるまで、他のメッセージは今後は表示されません。
アプリケーションが WSAEventSelect を呼び出すとき、または再有効化関数が呼び出されたときにネットワーク イベントが既に発生している場合は、ネットワーク イベントが記録され、関連するイベント オブジェクトが適切に設定されます。 たとえば、次のシーケンスを考えてみます。
- アプリケーションはリッスンを呼び出 します。
- 接続要求は受信されましたが、まだ受け入れられません。
- アプリケーションは、ソケットのFD_ACCEPT ネットワーク イベントに関心があることを指定して WSAEventSelect を呼び出します。 ネットワーク イベントの永続化により、Windows ソケットはFD_ACCEPTネットワーク イベントを記録し、関連付けられているイベント オブジェクトをすぐに設定します。
FD_OOB ネットワーク イベントは、OOB データを個別に受信するようにソケットが構成されている場合にのみ使用されます。 ソケットが OOB データをインラインで受信するように構成されている場合、OOB (優先) データは通常のデータとして扱われ、アプリケーションは関心を登録する必要があり、ネットワーク イベントではなく、ネットワーク イベント FD_OOB FD_READ取得します。 アプリケーションは、SO_OOBINLINE オプションに setsockopt または getsockopt を使用して、OOB データの処理方法を設定または検査できます。
FD_CLOSE ネットワーク イベントのエラー コードは、ソケットのクローズが正常か中止かを示します。 エラー コードが 0 の場合、クローズは正常です。エラー コードが WSAECONNRESET の場合は、ソケットの仮想回線がリセットされました。 これは、SOCK_STREAMなどの接続指向ソケットにのみ適用されます。
FD_CLOSE ネットワーク イベントは、ソケットに対応する仮想回線に対して近い表示が受信されたときに記録されます。 TCP の用語では、接続が TIME WAIT または CLOSE WAIT 状態になると、FD_CLOSEが記録されることを意味します。 これは、リモート エンドが送信側または closesocket でシャットダウンを実行した結果です。 すべてのデータがソケットから読み取られた後にポストされるFD_CLOSE。 データが失われる可能性を回避するために、アプリケーションはFD_CLOSEを受け取った時点で残りのデータをチェックする必要があります。 詳細については、「 グレースフル シャットダウン」、「残留オプション」、および「ソケットクロージャ」および シャットダウン機能に関するセクションを 参照 してください。
Windows ソケットでは、仮想回線のクローズを示すFD_CLOSEネットワーク イベントのみが記録されることに注意してください。 この状態を示すFD_READネットワーク イベントは記録されません。
FD_QOSまたはFD_GROUP_QOSネットワーク イベントは、ソケット に関連付けられているフロー仕様のパラメーターがある場合に記録されます。 アプリケーションでは、 WSAIoctl とコマンド SIO_GET_QOS を使用して、ソケット の現在のサービス品質を取得する必要があります。
FD_ROUTING_INTERFACE_CHANGE ネットワーク イベントは、 WSAIoctl で指定された宛先に到達するために使用する必要があるローカル インターフェイスが、このような IOCTL が発行された後 に SIO_ROUTING_INTERFACE_CHANGE変更されたときに記録されます。
FD_ADDRESS_LIST_CHANGE ネットワーク イベントは、 wsaIoctl と SIO_ADDRESS_LIST_CHANGE が発行された後にアプリケーションが変更をバインドできるソケットのプロトコル ファミリのアドレスの一覧が記録されます。
エラー コード | 意味 |
---|---|
WSANOTINITIALISED | この関数を使用する前に 、WSAStartup 呼び出しが正常に行われる必要があります。 |
WSAENETDOWN | ネットワーク サブシステムが失敗しました。 |
WSAEINVAL | 指定されたパラメーターのいずれかが無効であるか、指定されたソケットが無効な状態です。 |
WSAEINPROGRESS | ブロックしている Windows ソケット 1.1 呼び出しが進行中であるか、サービス プロバイダーがコールバック関数を処理しています。 |
WSAENOTSOCK | 記述子はソケットではありません。 |
注釈
WSAEventSelect 関数は、選択したFD_XXXネットワーク イベント (lNetworkEvents) に関連付けるイベント オブジェクト hEventObject を指定するために使用されます。 イベント オブジェクトが指定されているソケットは、 パラメーター によって識別されます。 イベント オブジェクトは、指定されたネットワーク イベントのいずれかが発生したときに設定されます。
WSAEventSelect 関数は WSAAsyncSelect とよく似ていますが、これは、指定されたネットワーク イベントが発生したときに実行されるアクションの違いです。 WSAAsyncSelect 関数を使用すると、アプリケーション指定の Windows メッセージがポストされます。 WSAEventSelect は、関連付けられたイベント オブジェクトを設定し、このイベントの発生を内部ネットワーク イベント レコードに記録します。 アプリケーションでは 、WSAWaitForMultipleEvents を 使用してイベント オブジェクトを待機またはポーリングし、 WSAEnumNetworkEvents を使用して内部ネットワーク イベント レコードの内容を取得し、指定されたネットワーク イベントのうちどれが発生したかを判断できます。
WSAEventSelect 関数で使用されるイベント オブジェクトの状態をリセットする適切な方法は、イベント オブジェクトのハンドルを hEventObject パラメーターの WSAEnumNetworkEvents 関数に渡すことです。 これにより、イベント オブジェクトがリセットされ、ソケット上のアクティブな FD イベントの状態がアトミックに調整されます。
WSAEnumNetworkEvents を使用してネットワーク アクティビティとエラーを記録および取得できるようにする唯一の関数は 、WSAEventSelect です。 select とWSAAsyncSelect の説明を参照して、これらの関数がネットワーク アクティビティとエラーを報告する方法を確認してください。
WSAEventSelect 関数は、lNetworkEventsの値に関係なく、ソケット s を非ブロッキング モードに自動的に設定します。 ソケットをブロック モードに戻すには、まず、WSAEventSelect の呼び出しを使用してソケットに関連付けられているイベント レコードをクリアし、lNetworkEvents を 0 に設定し、hEventObject パラメーターを NULL に設定する必要があります。 その後、 ioctlsocket または WSAIoctl を呼び出して、ソケットをブロッキング モードに戻すことができます。
lNetworkEvents パラメーターは、次の一覧で指定した値のいずれかで、ビットごとの OR 演算子を使用して構築されます。
値 | 意味 |
---|---|
FD_READ | 読み取り準備の通知を受け取る必要があります。 |
FD_WRITE | 書き込みの準備の通知を受け取る必要があります。 |
FD_OOB | OOB データの到着の通知を受け取る必要があります。 |
FD_ACCEPT | 受信接続の通知を受信する必要があります。 |
FD_CONNECT | 完了した接続またはマルチポイント結合操作の通知を受け取る必要があります。 |
FD_CLOSE | ソケットのクローズの通知を受け取る必要があります。 |
FD_QOS | ソケットの通知を受信する (QoS の変更。 |
FD_GROUP_QOS | ソケット グループで今後使用するために予約されています。 ソケット グループ QoS の変更の通知を受け取ります。 |
FD_ROUTING_ INTERFACE_CHANGE | 指定した宛先のルーティング インターフェイスの変更の通知を受け取る必要があります。 |
FD_ADDRESS_ LIST_CHANGE | ソケットのアドレス ファミリのローカル アドレス一覧の変更の通知を受け取る必要があります。 |
ソケット に対して WSAEventSelect を 発行すると、同じソケットの以前の WSAAsyncSelect または WSAEventSelect が取り消され、内部ネットワーク イベント レコードがクリアされます。 たとえば、イベント オブジェクトをネットワーク イベントの読み取りと書き込みの両方に関連付けるには、次のように、アプリケーションで WSAEventSelect をFD_READとFD_WRITEの両方で呼び出す必要があります。
rc = WSAEventSelect(s, hEventObject, FD_READ|FD_WRITE);
ネットワーク イベントごとに異なるイベント オブジェクトを指定することはできません。 次のコードは機能しません。2 番目の呼び出しでは最初のの呼び出しの効果が取り消され、FD_WRITEネットワーク イベントのみが hEventObject2 に関連付けられます。
rc = WSAEventSelect(s, hEventObject1, FD_READ);
rc = WSAEventSelect(s, hEventObject2, FD_WRITE); //bad
ソケット上のネットワーク イベントの関連付けと選択を取り消すには、 lNetworkEvents を 0 に設定する必要があります。この場合、 hEventObject パラメーターは無視されます。
rc = WSAEventSelect(s, hEventObject, 0);
closesocket を使用してソケットを閉じると、ソケットの WSAEventSelect で指定されたネットワーク イベントの関連付けと選択も取り消されます。 ただし、アプリケーションは WSACloseEvent を呼び出してイベント オブジェクトを明示的に閉じ、リソースを解放する必要があります。
accept 関数が呼び出されたときに作成されたソケットには、それを受け入れるために使用されるリッスン ソケットと同じプロパティがあります。 リッスンしているソケットに対して設定された WSAEventSelect 関連付けとネットワーク イベントの選択は、受け入れられたソケットに適用されます。 たとえば、リッスン しているソケットが hEventObject と FD_ACCEPT、FD_READ、FD_WRITEの WSAEventSelect 関連付けを持つ場合、そのリッスン ソケットで受け入れられるソケットには、同じ hEventObject に関連付けられたFD_ACCEPT、FD_READ、およびFD_WRITEネットワーク イベントも含まれます。 別の hEventObject またはネットワーク イベントが必要な場合、アプリケーションは WSAEventSelect を呼び出し、受け入れられたソケットと必要な新しい情報を渡す必要があります。
コード例
次の例では、 WSAEventSelect 関数の使用方法を示します。//-------------------------
// Declare and initialize variables
SOCKET ListenSocket;
WSAEVENT NewEvent;
sockaddr_in InetAddr;
//-------------------------
// Initialize listening socket
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//-------------------------
// Bind listening socket
InetAddr.sin_family = AF_INET;
InetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InetAddr.sin_port = htons(27015);
bind (ListenSocket, (SOCKADDR *) &InetAddr, sizeof(InetAddr));
//-------------------------
// Create new event
NewEvent = WSACreateEvent();
//-------------------------
// Associate event types FD_ACCEPT and FD_CLOSE
// with the listening socket and NewEvent
WSAEventSelect( ListenSocket, NewEvent, FD_ACCEPT | FD_CLOSE);
//----------------------
// Listen for incoming connection requests
// on the created socket
if (listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR)
printf("Error listening on socket.\n");
printf("Listening on socket...\n");
// Need an event handler added to handle connection requests
Windows Phone 8: この関数は、Windows Phone 8 以降の Windows Phone ストア アプリでサポートされています。
Windows 8.1とWindows Server 2012 R2: この関数は、Windows 8.1、Windows Server 2012 R2 以降の Windows ストア アプリでサポートされています。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows 8.1、Windows Vista [デスクトップ アプリ |UWP アプリ] |
サポートされている最小のサーバー | Windows Server 2003 [デスクトップ アプリのみ | UWP アプリ] |
対象プラットフォーム | Windows |
ヘッダー | winsock2.h |
Library | Ws2_32.lib |
[DLL] | Ws2_32.dll |