Win32 API 日本語リファレンス
ホーム › Networking.WinSock › LPFN_CONNECTEX

LPFN_CONNECTEX

コールバック

シグネチャ

BOOL LPFN_CONNECTEX(
    SOCKET s,
    SOCKADDR* name,
    INT namelen,
    void* lpSendBuffer,
    DWORD dwSendDataLength,
    DWORD* lpdwBytesSent,
    OVERLAPPED* lpOverlapped
);

パラメーター

フィールド型説明
sSOCKET接続されていない、事前にバインドされたソケットを識別する記述子。詳細については「解説」を参照してください。
nameSOCKADDR*接続先のアドレスを指定する sockaddr 構造体へのポインター。IPv4 の場合、sockaddr にはアドレスファミリとして AF_INET、接続先の IPv4 アドレス、接続先のポートが格納されます。IPv6 の場合、sockaddr 構造体にはアドレスファミリとして AF_INET6、接続先の IPv6 アドレス、接続先のポートが格納され、さらに IPv6 のフロー情報およびスコープ ID 情報が含まれることがあります。
namelenINTname パラメーターが指す sockaddr 構造体の長さ (バイト単位)。
lpSendBuffervoid*接続の確立後に転送されるバッファーへのポインター。このパラメーターは省略可能です。ConnectEx を呼び出す前に s に対して TCP_FASTOPEN オプションが有効になっている場合、このデータの一部は接続の確立中に送信されることがあります。
dwSendDataLengthDWORDlpSendBuffer パラメーターが指すデータの長さ (バイト単位)。lpSendBuffer パラメーターが NULL の場合、このパラメーターは無視されます。
lpdwBytesSentDWORD*正常に復帰した場合、このパラメーターは、接続の確立後に送信されたバイト数を示す DWORD 値を指します。送信されたバイトは、lpSendBuffer パラメーターが指すバッファーの内容です。lpSendBuffer パラメーターが NULL の場合、このパラメーターは無視されます。
lpOverlappedOVERLAPPED*要求の処理に使用される OVERLAPPED 構造体。lpOverlapped パラメーターは必ず指定する必要があり、NULL にすることはできません。

公式ドキュメント

ConnectEx 関数は、指定されたソケットへの接続を確立し、接続の確立後に必要に応じてデータを送信します。 ConnectEx 関数は、コネクション指向のソケットでのみサポートされます。

メモ  この関数は、Windows Sockets 仕様に対する Microsoft 固有の拡張です。

 

戻り値

成功した場合、ConnectEx 関数は TRUE を返します。失敗した場合、この関数は FALSE を返します。拡張エラー情報を取得するには、 WSAGetLastError 関数を使用します。 WSAGetLastError 関数の呼び出しが ERROR_IO_PENDING を返した場合、操作は正常に開始され、進行中です。この場合でも、オーバーラップ操作の完了時に呼び出しが失敗することがあります。

返されたエラーコードが WSAECONNREFUSED、WSAENETUNREACH、または WSAETIMEDOUT の場合、アプリケーションは同じソケットに対して ConnectEx、 WSAConnect、または connect を再度呼び出すことができます。

エラーコード 説明
WSANOTINITIALISED
ConnectEx を使用する前に、 WSAStartup 関数の呼び出しが成功している必要があります。
WSAENETDOWN
ネットワークサブシステムで障害が発生しました。
WSAEADDRINUSE
ソケットのローカルアドレスが既に使用されており、そのソケットには SO_REUSEADDR によるアドレスの再利用が設定されていません。このエラーは通常 bind 操作中に発生しますが、ローカル IP アドレスにワイルドカードアドレス (INADDR_ANY または in6addr_any) を指定して bind 関数を呼び出した場合は、 ConnectEx 関数の呼び出しまでエラーが遅延することがあります。この場合、ConnectEx 関数によって特定の IP アドレスが暗黙的にバインドされる必要があります。
WSAEALREADY
指定されたソケットで、非ブロッキングの connect、 WSAConnect、または ConnectEx 関数の呼び出しが進行中です。
WSAEADDRNOTAVAIL
リモートアドレスが ADDR_ANY などの無効なアドレスです ( ConnectEx 関数は、コネクション指向のソケットでのみサポートされます)。
WSAEAFNOSUPPORT
指定されたファミリのアドレスは、このソケットでは使用できません。
WSAECONNREFUSED
接続の試行が拒否されました。
WSAEFAULT
name、lpSendBuffer、または lpOverlapped パラメーターがユーザーアドレス空間の有効な部分を指していないか、namelen が小さすぎます。
WSAEINVAL
パラメーター s が、バインドされていないソケットまたはリッスン中のソケットです。
WSAEISCONN
ソケットは既に接続されています。
WSAENETUNREACH
現時点では、このホストからネットワークに到達できません。
WSAEHOSTUNREACH
到達できないホストに対してソケット操作が試行されました。
WSAENOBUFS
利用可能なバッファー領域がないため、ソケットを接続できません。
WSAENOTSOCK
記述子がソケットではありません。
WSAETIMEDOUT
接続を確立できないまま、接続の試行がタイムアウトしました。

解説(Remarks)

ConnectEx 関数は、複数のソケット関数を 1 回の API/カーネル遷移にまとめたものです。 ConnectEx 関数の呼び出しが正常に完了すると、次の操作が実行されます。

Windows Vista 以降を対象とするアプリケーションでは、クライアントアプリケーションの設計を大幅に簡素化できる WSAConnectByList 関数または WSAConnectByName 関数の使用を検討してください。

ConnectEx 関数は、コネクション指向のソケットでのみ使用できます。s パラメーターに渡すソケットは、ソケットの種類として SOCK_STREAM、SOCK_RDM、または SOCK_SEQPACKET を指定して作成する必要があります。

lpSendBuffer パラメーターは、接続の確立後に送信するデータのバッファーを指します。dwSendDataLength パラメーターは、送信するこのデータの長さをバイト単位で指定します。アプリケーションは、send 関数や WSASend 関数と同じように、ConnectEx を使用して大きなデータバッファーの送信を要求できます。ただし、ConnectEx の 1 回の呼び出しで巨大なバッファーを送信することは強く推奨されません。この操作では、バッファー全体が送信されるまで大量のシステムメモリリソースが使用されるためです。

ConnectEx 関数が成功した場合、接続が確立され、lpSendBuffer パラメーターが指すデータはすべて、name パラメーターが指す sockaddr 構造体で指定されたアドレスに送信されています。

メモ   ConnectEx 関数の関数ポインターは、実行時に SIO_GET_EXTENSION_FUNCTION_POINTER オペコードを指定して WSAIoctl 関数を呼び出して取得する必要があります。WSAIoctl 関数に渡す入力バッファーには、ConnectEx 拡張関数を識別する値を持つグローバル一意識別子 (GUID) である WSAID_CONNECTEX を格納する必要があります。成功すると、WSAIoctl 関数が返す出力に ConnectEx 関数へのポインターが格納されます。WSAID_CONNECTEX GUID は、Mswsock.h ヘッダーファイルで定義されています。
 

ConnectEx 関数はオーバーラップ I/O を使用します。そのため、ConnectEx 関数を使用すると、アプリケーションは比較的少数のスレッドで多数のクライアントを処理できます。これに対し、オーバーラップ I/O を使用しない WSAConnect 関数では、複数の要求を同時に受け取る場合、通常は接続要求ごとに個別のスレッドが必要になります。

メモ   あるスレッドが開始したすべての I/O は、そのスレッドの終了時に取り消されます。オーバーラップソケットの場合、操作が完了する前にスレッドが閉じられると、保留中の非同期操作が失敗することがあります。詳細については、ExitThread を参照してください。

 

コネクション指向のソケットでは、接続を直ちに完了できないことが多いため、操作が開始された時点で関数はすぐに ERROR_IO_PENDING または WSA_IO_PENDING エラーで復帰します。接続操作が完了して成功または失敗が確定すると、lpOverlapped で指定された完了通知メカニズムを使用して状態が報告されます。他のすべてのオーバーラップ関数の呼び出しと同様に、完了通知メカニズムとしてイベントまたは完了ポートを使用できます。 GetQueuedCompletionStatus、 GetOverlappedResult、または WSAGetOverlappedResult 関数の lpNumberOfBytesTransferred パラメーターは、要求で送信されたバイト数を示します。

ConnectEx 関数が正常に完了した場合、ソケットハンドル s は次の関数にのみ渡すことができます。

既に接続されているソケットに対して TF_DISCONNECT フラグと TF_REUSE_SOCKET フラグの両方を指定して TransmitFile 関数を呼び出すと、指定したソケットは、接続されていないがバインドされたままの状態に戻ります。この場合、そのソケットのハンドルを ConnectEx 関数の s パラメーターに渡すことはできますが、そのソケットを AcceptEx 関数の呼び出しで再利用することはできません。同様に、TransmitFile 関数を使用して再利用した受け入れ済みソケットを、ConnectEx の呼び出しで使用することもできません。なお、再利用したソケットの場合、ConnectEx は下位のトランスポートの動作の影響を受けます。たとえば、TCP ソケットは TCP の TIME_WAIT 状態の影響を受けることがあり、その結果 ConnectEx の呼び出しが遅延することがあります。

ConnectEx 関数が TRUE を返した時点で、ソケット s は接続済みソケットの既定の状態になっています。ソケット s では、SO_UPDATE_CONNECT_CONTEXT がソケットに設定されるまで、以前に設定したプロパティやオプションは有効になりません。SO_UPDATE_CONNECT_CONTEXT オプションを設定するには、 setsockopt 関数を使用します。

例:

//Need to #include <mswsock.h> for SO_UPDATE_CONNECT_CONTEXT

int iResult = 0;

iResult = setsockopt( s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 );

ConnectEx の実行中に接続が確立されたかどうかを確認するには、SO_CONNECT_TIME ソケットオプションを指定して getsockopt 関数を使用します。接続が確立されている場合、getsockopt 関数に渡した optval パラメーターに返される値は、そのソケットが接続されてからの秒数です。ソケットが接続されていない場合、返される optval パラメーターには 0xFFFFFFFF が格納されます。この方法で接続を確認することは、データをまったく送信しないまま一定時間接続が確立されたままになっていないかを判断するために必要です。そのような接続は終了することが推奨されます。

例:


//Need to #include <mswsock.h> for SO_CONNECT_TIME

int seconds;
int bytes = sizeof(seconds);
int iResult = 0;

iResult = getsockopt( s, SOL_SOCKET, SO_CONNECT_TIME,
                      (char *)&seconds, (PINT)&bytes );
if ( iResult != NO_ERROR ) {
    printf( "getsockopt(SO_CONNECT_TIME) failed with error: %u\n", 
        WSAGetLastError() );
}
else {
    if (seconds == 0xFFFFFFFF)
        printf("Connection not established yet\n");
    else
       printf("Connection has been established %ld seconds\n",
           seconds);
}
メモ  ソケットを開いた後に setsockopt を呼び出し、続いて sendto を呼び出すと、Windows Sockets は暗黙的に bind 関数を呼び出します。
 

name パラメーターが指す sockaddr 構造体のアドレスパラメーターがすべて 0 の場合、ConnectEx はエラー WSAEADDRNOTAVAIL を返します。アクティブな接続を再接続しようとすると、エラーコード WSAEISCONN で失敗します。

接続済みのソケットが何らかの理由で閉じられた場合は、そのソケットを破棄して新しいソケットを作成することが推奨されます。これは、接続済みソケットで何らかの問題が発生した場合、安定した状態に戻すためには、アプリケーションはそのソケットを破棄して必要なソケットを作成し直す必要があると想定するのが最も安全なためです。

DisconnectEx 関数を TF_REUSE_SOCKET フラグ付きで呼び出すと、指定したソケットは、接続されていないがバインドされたままの状態に戻ります。この場合、そのソケットのハンドルを ConnectEx 関数の s パラメーターに渡すことができます。

TCP が閉じた接続を解放してそのリソースを再利用できるようになるまでに経過する必要がある時間の間隔は、TIME_WAIT 状態または 2MSL 状態と呼ばれます。この間、接続は、新しい接続を確立する場合よりもはるかに低いコストでクライアントとサーバーの双方で再び開くことができます。

TIME_WAIT の動作は RFC 793 で規定されており、TCP はネットワークの最大セグメント有効期間 (MSL) の 2 倍以上の間、閉じた接続を保持する必要があります。接続が解放されると、そのソケットペアおよびソケットで使用されていた内部リソースを別の接続に使用できるようになります。

Windows の TCP は、接続の終了後に TIME_WAIT 状態になります。TIME_WAIT 状態の間は、ソケットペアを再利用できません。TIME_WAIT の期間は、TIME_WAIT の期間を秒単位で表す次の DWORD レジストリ設定を変更することで構成できます。

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters\TcpTimedWaitDelay

既定では、MSL は 120 秒と定義されています。TcpTimedWaitDelay レジストリ設定の既定値は 240 秒で、これは最大セグメント有効期間 120 秒の 2 倍、つまり 4 分に相当します。ただし、このエントリを使用して間隔をカスタマイズできます。

このエントリの値を小さくすると、TCP は閉じた接続をより早く解放し、新しい接続により多くのリソースを提供できます。ただし、値が小さすぎると、接続が完了する前に TCP が接続リソースを解放してしまい、サーバーが接続を再確立するために追加のリソースを使用する必要が生じる場合があります。

このレジストリ設定には 0 から 300 秒までの値を設定できます。

Windows Phone 8: この関数は、Windows Phone 8 以降の Windows Phone ストアアプリでサポートされます。

Windows 8.1 および Windows Server 2012 R2: この関数は、Windows 8.1、Windows Server 2012 R2 以降の Windows ストアアプリでサポートされます。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)