WSAAsyncSelect 関数 (winsock.h)

[ WSAAsyncSelect 関数は、[要件] セクションで指定されたオペレーティング システムで使用できます。 今後のバージョンでは変更されるか、利用できなくなる場合もあります。 Select スタイルの I/O を使用するのではなく、WinSock2 で 重複した I/O オブジェクトとイベント オブジェクト を使用します。

WSAAsyncSelect 関数は、ソケットのネットワーク イベントに関する Windows メッセージ ベースの通知を要求します。

構文

int WSAAsyncSelect(
  [in] SOCKET s,
  [in] HWND   hWnd,
  [in] u_int  wMsg,
  [in] long   lEvent
);

パラメーター

[in] s

イベント通知が必要なソケットを識別する記述子。

[in] hWnd

ネットワーク イベントが発生したときにメッセージを受信するウィンドウを識別するハンドル。

[in] wMsg

ネットワーク イベントが発生したときに受信するメッセージ。

[in] lEvent

アプリケーションが関心を持つネットワーク イベントの組み合わせを指定するビットマスク。

戻り値

WSAAsyncSelect 関数が成功した場合、ネットワーク イベント セットに対するアプリケーションの関心の宣言が成功した場合、戻り値は 0 になります。 それ以外の場合は、SOCKET_ERROR値が返され、 WSAGetLastError を呼び出すことによって特定のエラー番号を取得できます。

エラー コード 意味
WSANOTINITIALIZED
この関数を使用する前に、 WSAStartup 呼び出しが正常に行われる必要があります。
WSAENETDOWN
ネットワーク サブシステムが失敗しました。
WSAEINVAL
指定されたパラメーターの 1 つが無効です。たとえば、ウィンドウ ハンドルが既存のウィンドウを参照していないか、指定したソケットが無効な状態です。
WSAEINPROGRESS
ブロックしている Windows Sockets 1.1 呼び出しが進行中であるか、サービス プロバイダーがコールバック関数を処理しています。
WSAENOTSOCK
記述子はソケットではありません。
 

アプリケーション ウィンドウがメッセージを受信したときに、追加のエラー コードを設定できます。 このエラー コードは、WSAGETSELECTERROR マクロを使用して、応答メッセージの lParam から抽出されます。 ネットワーク イベントごとに考えられるエラー コードを次の表に示します。

イベント: FD_CONNECT

エラー コード 意味
WSAEAFNOSUPPORT 指定されたファミリーのアドレスをこのソケットと共に使用することはできません。
WSAECONNREFUSED 接続の試行が拒否されました。
WSAENETUNREACH 現在このホストからネットワークには到達できません。
WSAEFAULT namelen パラメーターが無効です。
WSAEINVAL ソケットは既にアドレスにバインドされています。
WSAEISCONN ソケットは既に接続されています。
WSAEMFILE ファイル記述子をこれ以上使用できません。
WSAENOBUFS バッファーに空き領域がありません。 ソケットを接続できません。
WSAENOTCONN ソケットは接続されていません。
WSAETIMEDOUT 接続を確立せずに、接続がタイムアウトしました。
 

イベント: FD_CLOSE

エラー コード 意味
WSAENETDOWN ネットワーク サブシステムが失敗しました。
WSAECONNRESET リモート側で接続がリセットされました。
WSAECONNABORTED タイムアウトまたはその他のエラーが原因で接続が終了しました。
 
エラー コード 意味
WSAENETDOWN ネットワーク サブシステムが失敗しました。
 

イベント: FD_ROUTING_INTERFACE_CHANGE

エラー コード 意味
WSAENETUNREACH 指定した宛先に到達できなくなりました。
WSAENETDOWN ネットワーク サブシステムが失敗しました。

注釈

WSAAsyncSelect 関数は、lEvent パラメーターで指定されたネットワーク イベントが検出されたときに、WS2_32.DLL がウィンドウ hWnd にメッセージを送信するように要求するために使用されます。 送信する必要があるメッセージは、 wMsg パラメーターによって指定されます。 通知が必要なソケットは 、 パラメーターによって 識別されます。

WSAAsyncSelect 関数は、lEvent の値に関係なく、ソケット s を非ブロッキング モードに自動的に設定します。 ソケットブロック モードに戻すには、まず、WSAAsyncSelect の呼び出しによってソケット関連付けられているイベント レコードをクリアし、lEvent を 0 に設定する必要があります。 その後、 ioctlsocket または WSAIoctl を呼び出して、ソケットをブロッキング モードに戻すことができます。 非ブロッキング ソケットをブロッキング モードに戻す方法の詳細については、 ioctlsocket 関数と WSAIoctl 関数を 参照してください。

lEvent パラメーターは、次の表に示す任意の値を持つビットごとの 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 ソケット プロトコル ファミリのローカル アドレス一覧の変更の通知を受け取ります。
 

ソケットに 対して WSAAsyncSelect を 発行すると、同じソケットの以前の WSAAsyncSelect または WSAEventSelect が取り消されます。 たとえば、読み取りと書き込みの両方の通知を受け取るために、アプリケーションは次のように、FD_READFD_WRITEの両方で WSAAsyncSelect を呼び出す必要があります。

rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);

イベントごとに異なるメッセージを指定することはできません。 次のコードは機能しません。2 番目の呼び出しでは最初の 呼び出しの効果が取り消され、 FD_WRITE イベントのみがメッセージ wMsg2 で報告されます。

rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);

Windows ソケットがソケット上のネットワーク イベントに関連するメッセージをそれ以上送信しない必要があることを示すすべての通知を取り消すには、 lEvent が 0 に設定されます。

rc = WSAAsyncSelect(s, hWnd, 0, 0);

WSAAsyncSelect は、このインスタンス内のソケットに対するイベント メッセージのポストをすぐに無効にしますが、メッセージがアプリケーション メッセージ キューで待機している可能性があります。 そのため、取り消し後もネットワーク イベント メッセージを受信するようにアプリケーションを準備する必要があります。 closesocket を使用してソケットを閉じると、WSAAsyncSelect メッセージの送信も取り消されますが、キュー内のメッセージに関する同じ注意事項が引き続き適用されます。

accept 関数によって作成されたソケットには、それを受け入れるために使用されるリッスン ソケットと同じプロパティがあります。 したがって、リッスンしているソケットに対して設定された WSAAsyncSelect イベントは、受け入れられたソケットにも適用されます。 たとえば、リッスンしているソケットに WSAAsyncSelect イベントFD_ACCEPTFD_READおよびFD_WRITEがある場合、そのリッスン ソケットで受け入れられるソケットには、メッセージに使用されるのと同じ wMsg 値を持つFD_ACCEPTFD_READおよびFD_WRITEイベントも含まれます。 別の wMsg またはイベントが必要な場合、アプリケーションは WSAAsyncSelect を呼び出し、受け入れられたソケットと目的の新しいデータを渡す必要があります。

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

メモイベント通知メッセージを受信すると、返されるエラー値が lParam の上位ワードの値と異なる可能性があるため、WSAGetLastError 関数を使用してエラー値をチェックすることはできません。
 
エラー コードとイベント コードは、Winsock2.h で次のように定義されている WSAGETSELECTERROR マクロと WSAGETSELECTEVENT マクロを使用して lParam から抽出できます。
#include <windows.h>

#define WSAGETSELECTEVENT(lParam)       LOWORD(lParam)
#define WSAGETSELECTERROR(lParam)       HIWORD(lParam)

これらのマクロを使用すると、アプリケーションのソース コードの移植性が最大化されます。

返される可能性のあるネットワーク イベント コードを次の表に示します。

意味
FD_READ ソケット 読み取り可能です。
FD_WRITE ソケット 書き込み準備ができています。
FD_OOB ソケット読み取る準備ができている OOB データ
FD_ACCEPT ソケット は、 新しい受信接続を受け入れる準備ができています。
FD_CONNECT ソケットで開始された接続またはマルチポイント 結合 操作 完了しました。
FD_CLOSE ソケット s によって識別される接続が閉じられました。
FD_QOS ソケット s に関連付けられているサービスの品質が変更されました。
FD_GROUP_QOS 予約済み。 s が属する ソケット グループに関連付けられているサービスの品質が変更されました (ソケット グループでの今後の使用のために予約されています)。
FD_ROUTING_INTERFACE_CHANGE 指定した宛先への送信に使用するローカル インターフェイスが変更されました。
FD_ADDRESS_LIST_CHANGE アプリケーション・クライアントがバインドできるソケット・プロトコル・ファミリーのアドレスのリストが変更されました。
 

WSAAsyncSelect は複数のイベントに関心を持って呼び出すことができますが、アプリケーション ウィンドウはネットワーク イベントごとに 1 つのメッセージを受信します。

select 関数の場合と同様に、WSAAsyncSelect は、データ転送操作 (送信または recv) を即時成功を期待していつ発行できるかを判断するために頻繁に使用されます。 それでも、堅牢なアプリケーションは、メッセージを受信し、 WSAEWOULDBLOCK をすぐに返す Windows ソケット 2 呼び出しを発行できる可能性に備える必要があります。 たとえば、次の一連のイベントを使用できます。

  1. データはソケットに到着します Windows ソケット 2 が WSAAsyncSelect メッセージを 投稿する
  2. アプリケーションが他のメッセージを処理する
  3. 処理中に、アプリケーションは を ioctlsocket(s, FIONREAD...) 発行し、読み取る準備ができているデータがあることを確認します
  4. アプリケーションは、 を recv(s,...) 発行してデータを読み取る
  5. アプリケーションは次のメッセージを処理するループを実行し、最終的にデータが読み取り可能であることを示す WSAAsyncSelect メッセージに到達します
  6. アプリケーションの問題 recv(s,...)WSAEWOULDBLOCK エラーで失敗します。
他の配列も可能である。

WS2_32.DLL は、特定のネットワーク イベントに対するメッセージをアプリケーションに継続的にフラッディングしません。 アプリケーション ウィンドウに特定のイベントの通知を正常にポストした後、アプリケーションがそのネットワーク イベントの通知を暗黙的に再び有効にする関数呼び出しを行うまで、そのネットワーク イベントのそれ以上のメッセージはアプリケーション ウィンドウに投稿されません。

イベント 再有効化関数
FD_READ recvrecvfromWSARecv、または WSARecvFrom
FD_WRITE sendsendtoWSASend、または WSASendTo
FD_OOB recvrecvfromWSARecv、または WSARecvFrom
FD_ACCEPT 条件関数がCF_DEFER返されたことを示すエラー コードがWSATRY_AGAIN場合を除き、accept または WSAAccept
FD_CONNECT [なし] :
FD_CLOSE [なし] :
FD_QOS WSAIoctl とコマンド SIO_GET_QOS。
FD_GROUP_QOS 予約済み。 WSAIoctl とコマンド SIO_GET_GROUP_QOS (ソケット グループで今後使用するために予約されています)。
FD_ROUTING_INTERFACE_CHANGE WSAIoctl とコマンド SIO_ROUTING_INTERFACE_CHANGE。
FD_ADDRESS_LIST_CHANGE WSAIoctl とコマンド SIO_ADDRESS_LIST_CHANGE。
 

再有効化ルーチンを呼び出すと、失敗したルーチンであっても、関連するイベントのメッセージポストが再び有効になります。

FD_READFD_OOBおよびFD_ACCEPTイベントの場合、メッセージの投稿はレベルによってトリガーされます。 つまり、再有効化ルーチンが呼び出され、呼び出し後も関連条件が満たされた場合、 WSAAsyncSelect メッセージがアプリケーションにポストされます。 これにより、アプリケーションはイベントドリブンになり、一度に到着するデータの量には関係ありません。 次の例について考えてみます。

  1. ネットワーク トランスポート スタックは、ソケット 100 バイトのデータを受け取り、Windows ソケット 2 に FD_READ メッセージを送信します。
  2. アプリケーションは recv( s, buffptr, 50, 0) を発行して 50 バイトを読み取ります。
  3. み取る データが残っているため、別のFD_READ メッセージが投稿されます。
これらのセマンティクスでは、アプリケーションは、FD_READ メッセージに応答して使用可能なすべてのデータを読み取る必要はありません。各FD_READ メッセージに応答する 1 つの recv が適切です。 アプリケーションが 1 つのFD_READに応答して複数の recv 呼び出しを発行すると、複数のFD_READ メッセージを受信できます。 このようなアプリケーションでは、FD_READ イベントが設定されていない状態で WSAAsyncSelect を呼び出すことによって、recv 呼び出しを開始する前に、FD_READ メッセージを無効にする必要があります。

FD_QOSイベントとFD_GROUP_QOS イベントはエッジ トリガーと見なされます。 サービスの品質の変更が発生すると、メッセージが 1 回だけ投稿されます。 プロバイダーがサービスの品質のさらなる変更を検出するか、アプリケーションがソケットのサービスの品質を再ネゴシエーションするまで、それ以上のメッセージは今後は表示されません。

FD_ROUTING_INTERFACE_CHANGE メッセージは、WSAIoctl で指定された宛先に到達するために使用する必要があるローカル インターフェイスが、そのような IOCTL が発行された後SIO_ROUTING_INTERFACE_CHANGE変更されたときに投稿されます。

FD_ADDRESS_LIST_CHANGE メッセージは、WSAIoctl と SIO_ADDRESS_LIST_CHANGEが発行された後に、アプリケーションがバインドできるアドレスの一覧が変更されたときに投稿されます。

アプリケーションが WSAAsyncSelect を呼び出したとき、または再有効化関数が呼び出されたときにイベントが発生した場合は、必要に応じてメッセージがポストされます。 たとえば、次のシーケンスを考えてみます。

  1. アプリケーションはリッスンを呼び出 します
  2. 接続要求は受信されますが、まだ受け入れられません。
  3. アプリケーションは WSAAsyncSelect を呼び出し、ソケット のメッセージFD_ACCEPT 受信する必要があることを指定します。 イベントの永続化により、Windows Sockets 2 は FD_ACCEPT メッセージを直ちに投稿します。

FD_WRITE イベントの処理方法が若干異なります。 ソケットが接続またはWSAConnect (FD_CONNECT後に登録されている場合) または accept または WSAAccept で受け入れられた場合、または送信操作が WSAEWOULDBLOCK で失敗し、バッファー領域が使用可能になったときに、FD_WRITE メッセージがポストされます。 したがって、アプリケーションは、最初の FD_WRITE メッセージから送信が可能であり、送信が WSAEWOULDBLOCK を返すまで持続すると想定できます。 このようなエラーが発生すると、アプリケーションは、 FD_WRITE メッセージで送信が可能であることを通知されます。

FD_OOB イベントは、OOB データを個別に受信するようにソケットが構成されている場合にのみ使用されます。 OOB データをインラインで受信するようにソケットが構成されている場合、OOB (優先) データは通常のデータとして扱われ、アプリケーションは関心のあるイベントを登録する必要があり、イベントFD_OOBではなく、 FD_READ イベント 受信します。 アプリケーションでは、SO_OOBINLINE オプションに setsockopt または getsockopt を使用して OOB データを処理する方法を設定または検査できます。

FD_CLOSE メッセージのエラー コードは、ソケットクローズが正常か中止かを示します。 エラー コードが 0 の場合、close は正常です。エラー コードが WSAECONNRESET の場合、ソケットの仮想回線がリセットされました。 これは、SOCK_STREAMなどの接続指向ソケットにのみ適用されます。

FD_CLOSE メッセージは、ソケットに対応する仮想回線に対してクローズ表示が受信されると投稿されます。 TCP の用語では、接続が TIME WAIT または CLOSE WAIT 状態になると、 FD_CLOSE がポストされることを意味します。 これは、リモート エンドが送信側または closesocketシャットダウンを実行した結果です。 FD_CLOSEは、すべてのデータがソケットから読み取られた後にのみ投稿する必要がありますが、データが失われる可能性を回避するために、FD_CLOSEを受け取った時点でアプリケーションが残りのデータをチェックする必要があります。

アプリケーションは仮想回線のクローズを示す FD_CLOSE メッセージのみを受け取り、受信したすべてのデータが正常に終了した場合にのみ受信されることに注意してください。 この条件を示す FD_READ メッセージは表示されません。

FD_QOSまたはFD_GROUP_QOS メッセージは、ソケット sまたは に属するソケット グループに関連付けられているフロー仕様のパラメーターがそれぞれ変更されたときに投稿されます。 アプリケーションでは、 WSAIoctl をコマンド SIO_GET_QOSまたはSIO_GET_GROUP_QOSと共に使用して、ソケット s または s が属しているソケット グループ 現在のサービス品質を取得する必要があります。

FD_ROUTING_INTERFACE_CHANGEイベントとFD_ADDRESS_LIST_CHANGE イベントもエッジ トリガーと見なされます。 アプリケーションが通知を要求した後に、SIO_ROUTING_INTERFACE_CHANGEまたはSIO_ADDRESS_LIST_CHANGEに対応して WSAIoctl を発行することで、変更が発生すると、メッセージが正確に 1 回投稿されます。 アプリケーションが IOCTL を再発行し、IOCTL が発行されたために別の変更が検出されるまで、それ以上のメッセージは出てこなくなります。

各非同期通知メッセージのイベントと条件の概要を次に示します。

  • FD_READ:
    1. WSAAsyncSelect が呼び出されたとき、現在受信できるデータがある場合。
    2. データが到着したとき( FD_READ がまだ投稿されていない場合)。
    3. recv または recvfrom が呼び出された後、データが引き続き受信できる場合は、MSG_PEEKの有無にかかわらず)。
      メモsetsockopt SO_OOBINLINEが有効になっている場合、データには、上記のインスタンスに通常のデータと OOB データの両方が含まれます。
       
  • FD_WRITE:
    1. WSAAsyncSelect が呼び出されたとき、送信または sendto が可能な場合。
    2. 接続または受け入れた後、接続が確立されたとき。
    3. SEND または sendtoWSAEWOULDBLOCK で失敗した後、send または sendto が成功する可能性が高い場合。
    4. コネクションレス ソケットで バインド した後。 FD_WRITE は、現時点で発生する場合と発生しない場合があります (実装に依存)。 いずれの場合も、コネクションレス ソケットは 、バインド 操作の直後に常に書き込み可能です。
  • FD_OOB: setsockopt SO_OOBINLINEが無効になっている場合にのみ有効です (既定値)。
    1. WSAAsyncSelect が呼び出されたとき、現在、MSG_OOB フラグを使用して受信できる OOB データがある場合。
    2. OOB データが到着したときに、 まだ 転記されていない場合FD_OOB。
    3. MSG_OOB フラグの有無にかかわらず recv または recvfrom が呼び出された後、OOB データが引き続き受信可能な場合。
  • FD_ACCEPT:
    1. WSAAsyncSelect が呼び出されたとき、現在、受け入れ可能な接続要求がある場合。
    2. 接続要求が到着したときに、まだ投稿されていない場合 FD_ACCEPT
    3. accept が呼び出された後、受 入れ可能な別の接続要求がある場合。
  • FD_CONNECT:
    1. WSAAsyncSelect が呼び出されたとき(現在接続が確立されている場合)。
    2. 接続が呼び出された後、接続が確立されると、接続がすぐに成功した場合でも、データグラム ソケットで一般的に行われます。
    3. WSAJoinLeaf を呼び出した後、結合操作が完了したとき。
    4. 接続後、WSAConnect、または WSAJoinLeaf が非ブロッキングの接続指向ソケットで呼び出されました。 最初の操作は WSAEWOULDBLOCK の特定のエラーで返されましたが、ネットワーク操作は先に進みます。 操作が最終的に成功したかどうかに関係なく、結果が決定されると、 FD_CONNECT が発生します。 クライアントはエラー コードをチェックして、結果が成功したか失敗したかを判断する必要があります。
  • FD_CLOSE: 接続指向ソケットでのみ有効 (たとえば、SOCK_STREAM)
    1. WSAAsyncSelect が呼び出されたとき、ソケット接続が閉じられている場合。
    2. リモート システムが正常終了を開始した後、現在受信できるデータがない場合 (リモート システムが正常終了を開始したときにデータが受信され、読み取りを待機している場合、保留中のすべてのデータが読み取られるまで 、FD_CLOSE は配信されないことに注意してください)。
    3. ローカル システムが シャットダウン で正常に閉じるのを開始した後、リモート システムは現在受信できるデータがないときに"データの終了" 通知 (TCP FIN など) で応答しました。
    4. リモート システムが接続を終了すると (送信された TCP RST など)、 lParam には WSAECONNRESET エラー値が含まれます。
      closesocket が呼び出された後は、FD_CLOSEは投稿されないことに注意してください。
       
  • FD_QOS:
    1. WSAAsyncSelect が呼び出されたとき、ソケットに関連付けられているサービスの品質が変更された場合。
    2. SIO_GET_QOSが呼び出された WSAIoctl の後、サービスの品質が変更されたとき。
  • FD_GROUP_QOS: 予約済み。
  • FD_ROUTING_INTERFACE_CHANGE:
    • SIO_ROUTING_INTERFACE_CHANGEを使用して WSAIoctl を呼び出した後、IOCTL で指定された宛先に到達するために使用する必要があるローカル インターフェイスが変更されたとき。
  • FD_ADDRESS_LIST_CHANGE:
    • SIO_ADDRESS_LIST_CHANGEを使用して WSAIoctl を呼び出した後、アプリケーションがバインドできるローカル アドレスの一覧が変更されたとき。

要件

要件
サポートされている最小のクライアント Windows 2000 Professional [デスクトップ アプリのみ]
サポートされている最小のサーバー Windows 2000 Server [デスクトップ アプリのみ]
対象プラットフォーム Windows
ヘッダー winsock.h (Winsock2.h を含む)
Library Ws2_32.lib
[DLL] Ws2_32.dll

こちらもご覧ください

WSAEventSelect

Winsock 関数

Winsock リファレンス

select