次の方法で共有


WSAAccept 関数 (winsock2.h)

WSAAccept 関数は、条件関数の戻り値に基づいて条件付きで接続を受け入れ、サービス フローの仕様の品質を提供し、接続データの転送を許可します。

構文

SOCKET WSAAPI WSAAccept(
  [in]      SOCKET          s,
  [out]     sockaddr        *addr,
  [in, out] LPINT           addrlen,
  [in]      LPCONDITIONPROC lpfnCondition,
  [in]      DWORD_PTR       dwCallbackData
);

パラメーター

[in] s

listen 関数の呼び出し後に接続をリッスンしているソケット 識別する記述子。

[out] addr

接続エンティティのアドレスを受け取る sockaddr 構造体への省略可能なポインター (通信層の既知)。 addr パラメーターの正確な形式は、ソケットの作成時に確立されたアドレス ファミリによって決まります。

[in, out] addrlen

addr パラメーターが指す sockaddr 構造体の長さをバイト単位で格納する整数への省略可能なポインター。

[in] lpfnCondition

パラメーターとして渡された呼び出し元情報に基づいて受け入れ/拒否の決定を行い、必要に応じて、この関数の結果パラメーターに適切な値を割り当てることでソケット グループを作成または結合する、アプリケーションが指定したオプションの条件関数 アドレス。 このパラメーターが NULL場合、条件関数は呼び出されません。

[in] dwCallbackData

条件関数に渡される dwCallbackData パラメーターの値として、アプリケーション指定の条件関数に返されるコールバック データ。 このパラメーターは、lpfnCondition パラメーターが NULLでない場合にのみ適用されます。 このパラメーターは、Windows ソケットでは解釈されません。

戻り値

エラーが発生しない場合、WSAAccept は、受け入れられたソケットの記述子である SOCKET 型の値を返します。 それ以外の場合は、INVALID_SOCKETの値が返され、WSAGetLastError呼び出すことによって特定のエラー コードを取得できます。

addrlen によって参照される整数には、最初に、addrが指す領域の量 含まれます。返されたアドレスの実際の長さ (バイト単位) が返されます。

エラー コード 意味
WSAEACCES の
アクセス許可によって禁止されている方法でソケットにアクセスしようとしました。 このエラーは、提供された接続要求がタイムアウトまたは取り消された場合に返されます。
WSAECONNREFUSED の
ターゲット マシンがアクティブに拒否したため、接続できませんでした。 このエラーは、条件関数 (CF_REJECT) の戻り値で示されているように、接続要求が強制的に拒否された場合に返されます。
WSAECONNRESET の
既存の接続がリモート ホストによって強制的に閉じられました。 このエラーは、着信接続が示されたが、その後、呼び出しを受け入れる前にリモート ピアによって終了された場合に返されます。
WSAEFAULT の
システムは、呼び出しでポインター引数を使用しようとしたときに、無効なポインター アドレスを検出しました。 このエラーは、addrlen パラメーターが小さすぎるか、addr または lpfnCondition がユーザー アドレス空間の一部ではない 返されます。
WSAEINTR の
WSACancelBlockingCall呼び出しによってブロック操作が中断されました。 このエラーは、ブロックしている Windows ソケット 1.1 呼び出しが WSACancelBlockingCallキャンセルされた場合に返されます。
WSAEINPROGRESS を する
ブロック操作は現在実行中です。 このエラーは、ブロックしている Windows ソケット 1.1 呼び出しが進行中の場合に返されます。
WSAEINVAL の
無効な引数が指定されました。 このエラーは、wsAAcceptを する前にリッスン 呼び出されなかった場合、条件関数の戻り値が有効でない場合、または指定したソケットが無効な状態にある場合に返されます。
WSAEMFILE の
開いているソケットが多すぎます。 このエラーは、WSAAccept への入力時にキューが空でない場合 返され、使用可能なソケット記述子がない場合です。
WSAENETDOWN の
ソケット操作で、ネットワークが停止しました。 このエラーは、ネットワーク サブシステムが失敗した場合に返されます。
WSAENOBUFS の
システムに十分なバッファー領域がなかったか、キューがいっぱいであるため、ソケットに対する操作を実行できませんでした。 このエラーは、使用可能なバッファー領域がない場合に返されます。
WSAENOTSOCK の
ソケットではないものに対して操作が試行されました。 このエラーは、s パラメーターで渡されたソケット記述子がソケットでない場合に返されます。
WSAEOPNOTSUPP の
プロトコル ファミリがシステムに構成されていないか、実装が存在しません。 このエラーは、参照先のソケットが接続指向サービスをサポートする型でない場合に返されます。
WSAEWOULDBLOCK を する
非ブロッキング ソケット操作をすぐに完了できませんでした。 このエラーは、ソケットが非ブロッキングとしてマークされていて、受け入れられる接続がない場合に返されます。
WSANOTINITIALIZED の
アプリケーションが WSAStartup呼び出していないか、WSAStartup 失敗しました。 このエラーは、この関数を使用する前に、WSAStartup 関数の dit が正常に呼び出された場合に返されます。
WSATRY_AGAIN
これは通常、ホスト名の解決中に一時的なエラーであり、ローカル サーバーが権限のあるサーバーから応答を受信しなかったことを意味します。 このエラーは、条件関数 (CF_DEFER) の戻り値で示されているように、接続要求の受け入れが遅延された場合に返されます。

備考

WSAAccept 関数は、ソケット で保留中の接続のキュー上の最初の接続を抽出し、条件関数が指定されている場合 (つまり、NULLではなく) 条件関数と照合します。 条件関数がCF_ACCEPTを返す場合は、WSAAccept 新しいソケットを作成します。 新しく作成されたソケットには、WSAAsyncSelect または WSAEventSelectで登録された非同期イベント 含む、ソケット と同じプロパティ 含まれます。 条件関数がCF_REJECTを返す場合、WSAAccept 接続要求を拒否します。 条件関数は、この関数と同じスレッドで実行され、できるだけ早く戻る必要があります。 決定を直ちに行うことができない場合、条件関数は、決定が行われなかったことを示すCF_DEFERを返す必要があり、この接続要求に関するアクションはサービス プロバイダーによって実行されません。 アプリケーションは、接続要求に対してアクションを実行する準備ができたら、WSAAccept 再度呼び出し、条件関数から戻り値としてCF_ACCEPTまたはCF_REJECTを返します。

既定モードのソケット (ブロック) は、アプリケーションが WSAAccept 呼び出し、キューで保留中の接続がない場合、接続が存在するまでブロックされます。

アプリケーションが WSAAccept 呼び出し、キューで保留中の接続がない場合、WSAEWOULDBLOCK エラーで非ブロッキング モード (ブロック) のソケットが失敗します。 WSAAccept 成功し、新しいソケット ハンドルを返した後、受け入れられたソケットを使用してそれ以上の接続を受け入れることはできません。 元のソケットは開いたままで、新しい接続要求をリッスンします。

addr パラメーターは、通信層に知られているように、接続エンティティのアドレスが入力された結果パラメーターです。 addr パラメーターの正確な形式は、通信が行われているアドレス ファミリによって決まります。 addrlen は値の結果パラメーターです。最初に、addrが指す領域の量 含める必要があります。戻り値には、返されたアドレスの実際の長さ (バイト単位) が含まれます。 この呼び出しは、SOCK_STREAMなどの接続指向のソケット型で使用されます。 addrlen または addrlen が NULL等しい場合、受け入れられたソケットのリモート アドレスに関する情報は返されません。 それ以外の場合、接続が正常に受け入れられると、これら 2 つのパラメーターが入力されます。

条件関数のプロトタイプは、次のように、Winsock2.h ヘッダー ファイルで LPCONDITIONPROCとして定義されます。

int CALLBACK 
ConditionFunc( 
  IN     LPWSABUF    lpCallerId, 
  IN     LPWSABUF    lpCallerData, 
  IN OUT LPQOS       lpSQOS, 
  IN OUT LPQOS       lpGQOS,
  IN     LPWSABUF    lpCalleeId, 
  IN     LPWSABUF    lpCalleeData, 
  OUT    GROUP FAR * g, 	
  IN     DWORD_PTR   dwCallbackData
);

ConditionFunc は、アプリケーション指定のコールバック関数のプレースホルダーです。 実際の条件関数は、DLL またはアプリケーション モジュール内に存在する必要があります。 これはモジュール定義ファイルにエクスポートされます。

lpCallerId パラメーターは、接続エンティティのアドレスを含む WSABUF 構造体を指します。ここで、len パラメーターはバッファーの長さ (バイト単位)、buf パラメーターはバッファーへのポインターです。 lpCallerData は、ユーザー データを含む値パラメーターです。 これらのパラメーターの情報は、接続要求と共に送信されます。 呼び出し元 ID または呼び出し元データが使用できない場合、対応するパラメーターは NULLされます。 多くのネットワーク プロトコルでは、接続時の呼び出し元データはサポートされていません。 ほとんどの従来のネットワーク プロトコルでは、接続要求時に呼び出し元識別子情報をサポートすることが期待できます。 WSABUF の buf 部分 lpCallerId が指 sockaddrを指します。 sockaddr 構造体は、そのアドレス ファミリに従って解釈されます (通常、sockaddr をアドレス ファミリに固有の型にキャストします)。

lpSQOS パラメーターは、呼び出し元によって指定されたソケット FLOWSPEC 構造体を参照し、その後にプロバイダー固有の追加パラメーターが続きます。 送信側または受信フローの指定値は、単一方向ソケットに対して適切に無視されます。 NULL 値は、呼び出し元が提供するサービス品質がなく、ネゴシエーションが不可能であることを示します。 lpSQOS ポインターNULL は、サービスの品質ネゴシエーションが行われること、またはプロバイダーがネゴシエーションなしでサービス要求の品質を受け入れる準備ができていることを示します。

lpGQOS パラメーターは予約されており、NULLする必要があります。 (ソケット グループで将来使用するために予約されています) は、呼び出し元が作成するソケット グループの FLOWSPEC 構造体を参照します。各方向に 1 つずつ、その後にプロバイダー固有の追加パラメーターが続きます。 lpGQOSNULL、呼び出し元が指定したグループのサービス品質がないことを示します。 ネゴシエーションが発生する場合は、サービスの品質情報を返すことができます。

lpCalleeId は、接続されたエンティティのローカル アドレスを含むパラメーターです。 lpCalleeId が指す WSABUF の buf 部分は、sockaddr 構造体を指しています。 sockaddr 構造体は、アドレス ファミリに従って解釈されます (通常は、sockaddr を、構造体 sockaddr_inなどのアドレス ファミリに固有の型にキャストします)。

lpCalleeData は、接続エンティティにユーザー データを返すために条件関数によって使用される結果パラメーターです。 lpCalleeData-len には、最初にサービス プロバイダーによって割り当てられ、lpCalleeData-bufによって指 バッファーの長さが含まれます。 値が 0 の場合は、呼び出し元にユーザー データを戻すことがサポートされていないことを意味します。 条件関数は、最大 lpCalleeData-len バイトのデータを lpCalleeData-bufにコピーし、転送された実際のバイト数を示すために lpCalleeData-len 更新する必要があります。 呼び出し元にユーザー データを返さない場合、条件関数は lpCalleeData-len ゼロに設定する必要があります。 すべてのアドレスとユーザー データの形式は、ソケットが属するアドレス ファミリに固有です。

g パラメーターは、条件関数内で割り当てられ、次のいずれかのアクションを示します。

  • g が既存のソケット グループ識別子 場合は、このグループによって設定されたすべての要件が満たされていれば、 をこのグループに追加します。
  • g = SG_UNCONSTRAINED_GROUP 場合は、制約のないソケット グループを作成し、最初のメンバーとして します。
  • g = SG_CONSTRAINED_GROUP 場合は、制約付きソケット グループを作成し、最初のメンバーとして します。
  • g = 0 の場合、グループ操作は実行されません。
制約のないグループの場合、1 つのサービス プロバイダーでサポートされている限り、ソケットのセットをグループ化できます。 制約付きソケット グループは、接続指向ソケットのみで構成でき、すべてのグループ化されたソケットの接続が同じホスト上の同じアドレスに存在する必要があります。 新しく作成されたソケット グループの場合、レベルの パラメーターを SOL_SOCKET に設定し、optname パラメーターを SO_GROUP_IDに設定した getsockopt 関数を使用して、新しいグループ識別子を取得できます。 ソケット グループとそれに関連付けられているソケット グループ ID は、このソケット グループに属する最後のソケットが閉じられるまで有効なままです。 ソケット グループ ID は、特定のサービス プロバイダーのすべてのプロセスで一意です。 ソケット グループとそれに関連付けられている識別子は、このソケット グループに属する最後のソケットが閉じられるまで有効なままです。 ソケット グループ識別子は、特定のサービス プロバイダーのすべてのプロセスで一意です。 ソケット グループの詳細については、WSASocket 関数の解説を参照してください。

条件関数に渡される dwCallbackData パラメーター値は、元の WSAAccept 呼び出しで dwCallbackData パラメーターとして渡される値です。 この値は、Windows ソケット バージョン 2 クライアントによってのみ解釈されます。 これにより、クライアントは、WSAAccept 呼び出しサイトから条件関数にコンテキスト情報を渡すことができます。 これにより、接続を受け入れるかどうかを判断するために必要な追加情報が条件関数に提供されます。 一般的な使用法は、このソケットが関連付けられているアプリケーション定義オブジェクトへの参照を含むデータ構造に (適切にキャストされた) ポインターを渡すことです。

注意WSAAccept 関数の使用を SYN 攻撃から保護するには、アプリケーションは接続要求を報告する前に完全な TCP ハンドシェイク (SYN-SYNACK-ACK) を実行する必要があります。 この方法で SYN 攻撃から保護すると、SO_CONDITIONAL_ACCEPT ソケット オプションが動作しなくなっています。条件付き関数は引き続き呼び出され、WSAAccept 関数 は正常に動作しますが、ハンドシェイクを実行できないクライアントに依存するサーバー アプリケーションは正常に動作しません。
 
注意 WSAAcceptなどのブロック Winsock 呼び出し 発行する場合、Winsock は呼び出しを完了する前にネットワーク イベントを待機する必要がある場合があります。 Winsock は、この状況でアラート可能な待機を実行します。この待機は、同じスレッドでスケジュールされた非同期プロシージャ 呼び出し (APC) によって中断される可能性があります。 同じスレッドで進行中の Winsock 呼び出しを中断した別のブロック Winsock 呼び出しを APC 内で発行すると、未定義の動作が発生し、Winsock クライアントが試行してはなりません。
 

コード例

次の例では、WSAAccept 関数の使用を示します。
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>

/* Define an example conditional function that depends on the pQos field */
int CALLBACK ConditionAcceptFunc(
    LPWSABUF lpCallerId,
    LPWSABUF lpCallerData,
    LPQOS pQos,
    LPQOS lpGQOS,
    LPWSABUF lpCalleeId,
    LPWSABUF lpCalleeData,
    GROUP FAR * g,
    DWORD_PTR dwCallbackData
    )
{

    if (pQos != NULL) {
        RtlZeroMemory(pQos, sizeof(QOS));
        return CF_ACCEPT;
    } else
        return CF_REJECT;
}

int main() {

    /* Declare and initialize variables */
    WSADATA wsaData;
    SOCKET ListenSocket, AcceptSocket;
    struct sockaddr_in saClient;
    int iClientSize = sizeof(saClient);
    u_short port = 27015;
    char* ip;
    sockaddr_in service;
    int error;

    /* Initialize Winsock */
    error = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (error) {
        printf("WSAStartup() failed with error: %d\n", error);
        return 1;
    }

    /* Create a TCP listening socket */
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {  
        printf("socket() failed with error: %d\n", WSAGetLastError() );
        WSACleanup();
        return 1;
    }

    /*-----------------------------------------  
     *  Set up the sock addr structure that the listening socket
     *  will be bound to. In this case, the structure holds the
     * local IP address and the port specified. */
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    hostent* thisHost;
    thisHost = gethostbyname("");
    ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
    service.sin_addr.s_addr = inet_addr(ip);

    /*-----------------------------------------
     *  Bind the listening socket to the IP address.
     * and port number specified by the sockaddr structure. */
    error = bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
    if (error == SOCKET_ERROR) {  
        printf("bind() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
  
    /* Make the socket listen for incoming connection requests */
    error = listen(ListenSocket, 1);
    if (error == SOCKET_ERROR) {  
        printf("listen() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    printf("Listening...\n");
  
    /*-----------------------------------------
     *  Accept an incoming connection request on the
     *  listening socket and transfer control to the 
     * accepting socket. */
    AcceptSocket = WSAAccept(ListenSocket, (SOCKADDR*) &saClient, &iClientSize, 
        &ConditionAcceptFunc, NULL);
 
    /*  Now do some work with the AcceptSocket 
     *  At this point, the application could
     *  handle data transfer on the socket, or other socket
     * functionality.*/
    
    /* Then clean up and quit */

    closesocket(AcceptSocket);
    closesocket(ListenSocket);
    WSACleanup();

    return 0;
}

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 アプリ]
ターゲット プラットフォーム の ウィンドウズ
ヘッダー winsock2.h
ライブラリ Ws2_32.lib
DLL Ws2_32.dll

関連項目

WSAAsyncSelect の

WSAConnect の

WSASocket の

Winsock Functions

Winsock リファレンス

を受け入れる

バインド

接続

getsockopt

をリッスンする

を選択

sockaddr を する

ソケット