bind関数はローカルアドレスとソケットを関連付けます。
int bind(
SOCKET s,
const struct sockaddr *name,
int namelen
);
WS2_32.DLL
バインドされていないソケットを識別するディスクリプタを指定します。
バインドされるソケットに割り当てるローカルアドレスのsockaddr構造体へのポインタを指定します。
nameパラメータが指すsockaddr構造体の長さをバイト単位で指定します。
成功すると0を返します。
失敗すると-1 (SOCKET_ERROR) を返します。特定のエラーコードを取得するにはWSAGetLastError関数を呼び出します。
ブロッキングソケットでは、戻り値は接続試行が成功または失敗したことを示します。
非ブロッキングソケットを使用した場合、接続試行は直ちに完了しない可能性があります。この場合、connectはSOCKET_ERRORを返し、WSAGetLastErrorはWSAEWOULDBLOCKを返します。この場合、3つのケースが考えられます。
select関数を使用して、ソケットが書き込み可能であるかどうかを確かめることによって、接続要求が完了したかどうかを決定します。
アプリケーションが接続イベントを監視するためにWSAEventSelectを使用している場合、アプリケーションはconnect操作が(成功または失敗により)完了したことを示すFD_CONNECT通知を受け取ります。
アプリケーションが接続イベントを監視するためにWSAEventSelectを使用している場合、関連付けられたイベントオブジェクトはシグナル状態となってconnect操作が(成功または失敗により)完了したことを示します。
非ブロッキングソケットにおける接続の確立が完了するまで、同一のソケットに対してconnect以降のすべての呼び出しはエラーコードWSAEALREADYで、また、接続が正常に完了した場合はエラーコードWSAEISCONNで失敗します。Windows Sockets 1.1仕様のあいまいさのため、接続が未解決の間にconnectから返されるエラーコードは実装間で異なる可能性があります。そのため、アプリケーションがconnectの複数回の呼び出しを使用して接続の完了を検出することは推奨されません。そのようなことを行う場合は、アプリケーションは、堅牢な実行を保証するために、WSAEALREADYエラー値を処理する場合と同じ方法でWSAEINVALおよびWSAEWOULDBLOCKエラー値を処理する準備ができていなければなりません。
setsockoptオプションSO_BROADCASTが有効でないため、ダイアグラムソケットのブロードキャストアドレスへの関連付けの試行が失敗しました。
以下のいずれかの要因によりエラーが発生しました。
そのソケットはすでにアドレスに関連付けられています。
ブロッキングWindows Sockets 1.1呼び出しが実行中であるか、サービスプロバイダがコールバック関数を実行中です。
sパラメータで指定されたディスクリプタはソケットではありません。
コンピュータ上のプロセスがすでに同じアドレスにバインドしており、そのソケットがアドレスを再利用可能となるようにSO_REUSEADDRソケットオプションが付けられていません。例えば、nameパラメータで指定されたIPアドレスとポート番号はすでにほかのアプリケーションが使用している別のソケットに関連付けられています。
nameパラメータで指定されたアドレスがこのコンピュータで有効なIPアドレスではありません。
ネットワークサブシステムが失敗しました。
利用可能なバッファ空間がありません。接続が多すぎます。
この関数を呼び出す前にWSAStartup関数の呼び出しが成功していなければなりません。
bind関数は、listen関数を呼び出す前に、未接続のソケットに対して呼び出す必要があります。この関数は通常、コネクション指向(ストリーム)ソケットまたはコネクションレス(ダイアグラム)ソケットに関連付けるために使用されます。また、bind関数は、生ソケット(socket関数呼び出し時にtypeパラメータにSOCK_RAWを渡して作成されたソケット)に関連付けるために使用される場合があります。送信操作の前に、connect, ConnectEx, WSAConnect, WSAConnectByList, WSAConnectByName呼び出しよりも前に未接続のソケットに対してbind関数を使用することもできます。
socket関数呼び出しによりソケットを作成した時、そのソケットは名前空間(アドレスファミリ)内にはに存在するものの、名前が割り当てられていません。bind関数を使用すると、名前の付けられていないソケットに対してローカルな名前を割り当てることによって、ローカルな接続を確立します。
インターネットアドレスファミリを使用する場合、名前は3つの部分から構成されます。
Windows Sockets 2では、nameパラメータがsockaddr構造体のポインタであると厳密に解釈しません。これは、Windows Sockets 1.1互換性のためのキャストです。サービスプロバイダは、nameパラメータをサイズnamelenのメモリブロックのポインタとして自由に扱うことができます。このメモリブロックの最初の2バイト(sockaddr構造体のsa_familyメンバ、sockaddr_in構造体のsin_familyメンバ、あるいはsockaddr_in6構造体のsin6_familyメンバに相当)には、ソケットを作成するのに使用されたアドレスファミリが含まれていなければいけません。それ以外の場合は、WSAEFAULTエラーが発生します。
アプリケーションは、どのローカルアドレスが割り当てらても構わないのであれば、IPv4ローカルアドレスに対しては定数0x00000000 (INADDR_ANY) を、IPv6ローカルアドレスに対しては定数in6addr_any(すべてのメンバの値が0のin6_addr構造体)をnameパラメータのsa_dataメンバに指定します。これにより、下層のサービスプロバイダは、どれでも適切なネットワークアドレスを使用することができ、将来的に、マルチホームホスト(複数のネットワークインターフェースおよびネットワークアドレスを持つホスト)環境下でのアプリケーションプログラミングを簡単にすることができる可能性があります。
TCP/IPでは、ポート番号に0を指定すると、サービスプロバイダは動的クライアントポート番号の範囲の中からユニークなポート番号をアプリケーションに割り当てます。Windows Vista以降では、動的クライアントポート番号の範囲は49152~65535です。この値はWindows Server 2003以前のもの(1025~5000)から変更されています。動的ポート番号の最大値は、以下のレジストリキーの下にある値を設定することにより変更できます。
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
このレジストリキーの下のMaxUserPort値は、動的クライアントポート番号の範囲の最大値に使用される値を設定します。この値を変更して反映させるにはコンピュータを再起動させなければいけません。
Windows Vista以降では、動的クライアントポート番号の範囲をnetshコマンドで表示または設定することができます。動的クライアントポート番号の範囲は、UDPとTCPで、また、IPv4とIPv6に対して、別々に設定することができます。
アプリケーションはbindの後にgetsockname関数を使用して、ソケットに割り当てられたアドレスとポート番号を知ることができます。インターネットアドレスがINADDR_ANYまたはin6addr_anyである場合は、getsockname関数は、ソケットが接続されるまでは必ずしもアドレスを提供できるとは限りません。これは、ホストがマルチホームである場合にそれぞれのアドレスが有効である可能性があるためです。クライアントアプリケーションでは、0ではない特定のポート番号にソケットを関連付けることは、すでにローカルコンピュータ上で同じポート番号を使用している別のソケットと衝突する可能性があるため推奨されません。
Note: SO_EXCLUSIVEADDRUSEまたはSO_REUSEADDRソケットオプションを持つソケットでbindを使用する場合は、bindを呼び出すよりも前にソケットオプションを設定しておかなければいけません。
マルチキャスト操作において推奨される方法は、bind関数でソケットをローカルアドレスに関連付け、その後にマルチキャストグループに参加します。この操作の順序は強制ではありませんが、強く推奨されます。そのため、マルチキャストアプリケーションはまず最初にローカルコンピュータ上のIPv4またはIPv6アドレス、ワイルドカードIPv4アドレス(INADDR_ANY)、ワイルドカードIPv6アドレス(in6addr_any)のいずれかを選択します。次に、マルチキャストアプリケーションはこのアドレスをnameパラメータのsa_dataメンバに指定してbind関数を呼び出し、そのローカルIPアドレスをソケットに結び付けます。ワイルドカードアドレスを指定した場合は、Windowsが使用するローカルIPアドレスを選択します。bind関数が完了すると、アプリケーションは関心のあるマルチキャストグループに参加します。このソケットを使用して、recv, recvfrom, WSARecv, WSARecvEx, WSARecvFrom, WSARecvMsg関数でマルチキャストグループからのマルチキャストパケットを受信することができます。
通常、マルチキャストグループへの送信操作ではbind関数は必要ではありません。ソケットがまだアドレスに関連付けられていない場合、sendto, WSASendMsg, WSASendTo関数は暗黙のうちにソケットをワイルドカードアドレスに結び付けます。sendまたはWSASend関数では、暗黙の結合は行われず、また、これらの関数は接続済みのソケットのみが許されているので、これらの関数を使用する場合は、それより前にbind関数を呼び出す必要があります。すなわち、ソケットを接続するためには、すでにアドレスに関連付けられていなければいけません。アプリケーションが複数のネットワークインターフェースとローカルIPアドレスを持つローカルコンピュータ上で特定のローカルIPアドレスを選択したい場合には、sendto, WSASendMsg, WSASendTo関数を使用して送信操作を行う前にbind関数を使用することができます。もしそうしない場合には、sendto, WSASendMsg, WSASendTo関数によるワイルドカードアドレスへの暗黙の関連付けがにより、送信操作によって異なるローカルIPアドレスが使用されるようになります。
Note: bindなどのブロッキングWinsock関数を呼び出す場合、Winsockは呼び出しが完了する前にネットワークイベントの待機を必要とする場合があります。そのような状況ではWinsockはアラート可能な待機を行いますが、この待機中に、同じスレッドでスケジューリングされている非同期プロシージャコール(APC)による割り込み処理が行われる可能性があります。あるブロッキングWinsock呼び出し中にAPC割り込みが発生し、その中で別のブロッキングWinsock呼び出しを行うと未定義の動作を引き起こします。そのため、Winsockクライアントはこのような呼び出しをしようとしてはいけません。
以下のことに注意を払う必要があります。