次の方法で共有


IPv6 Winsock アプリケーションの Dual-Stack ソケット

Service Pack 1 (SP1) と Windows Server 2003 で Windows XP で IPv4 と IPv6 の両方をサポートするには、アプリケーションで、IPv4 で使用するソケットと IPv6 で使用するソケットの 2 つを作成する必要があります。 これら 2 つのソケットは、アプリケーションによって個別に処理される必要があります。

Windows Vista 以降では、IPv6 と IPv4 の両方のトラフィックを処理できる単一の IPv6 ソケットを作成できます。 たとえば、IPv6 用の TCP リッスン ソケットが作成され、デュアル スタック モードになり、ポート 5001 にバインドされます。 このデュアルスタック ソケットは、ポート 5001 に接続する IPv6 TCP クライアントと、ポート 5001 に接続する IPv4 TCP クライアントからの接続を受け入れます。 この機能により、アプリケーションの設計が大幅に簡素化され、2 つの別個のソケットに操作を投稿するために必要なリソースオーバーヘッドが削減されます。

Dual-Stack ソケットの作成

既定では、Windows Vista 以降で作成された IPv6 ソケットは、IPv6 プロトコル経由でのみ動作します。 IPv6 ソケットをデュアルスタック ソケットにするには、setsockopt 関数を IPV6_V6ONLY ソケット オプションで呼び出して、ソケットを IP アドレスにバインドする前に、この値を 0 に設定する必要があります。 IPV6_V6ONLY ソケット オプションを 0 に設定すると、AF_INET6 アドレス ファミリ用に作成されたソケットを使用して、IPv6 アドレスまたは IPv4 マップド アドレスとの間でパケットを送受信できます。

Dual-Stack ソケットを使用した IP アドレス

デュアルスタック ソケットには常に IPv6 アドレスが必要です。 IPv4 アドレスを操作するには、IPv4 マップの IPv6 アドレス形式を使用する必要があります。 IPv4 アドレスは、IPv4 マップの IPv6 アドレス形式で表す必要があります。これにより、IPv6 のみのアプリケーションが IPv4 ノードと通信できるようになります。 IPv4 マップの IPv6 アドレス形式を使用すると、IPv4 ノードの IPv4 アドレスを IPv6 アドレスとして表すことができます。 IPv4 アドレスは IPv6 アドレスの下位 32 ビットにエンコードされ、上位 96 ビットは固定プレフィックス 0:0:0:0:0:0:FFFF を保持します。 IPv4 マップ IPv6 アドレス形式は RFC 4291 で指定されています。 詳細については、www.ietf.org/rfc/rfc4291.txtを参照してください。 Mstcpip.h の IN6ADDR_SETV4MAPPED マクロを使用して、IPv4 アドレスを必要な IPv4 マップ IPv6 アドレス形式に変換できます。

基になるプロトコルが実際に IPv4 である場合、IPv4 アドレスは IPv4 マップされた IPv6 アドレス形式にマップされます。 つまり、SOCKADDR 構造体のファミリ フィールドはAF_INET6を示しますが、IPv4 マップの IPv6 アドレスは IPv6 アドレス構造でエンコードされます。 リッスン モードのデュアル スタック ソケットの場合、受け入れられた IPv4 接続は IPv4 マップされた IPv6 アドレスを返します。 IPv4 宛先に接続しているデュアル スタック ソケットの場合、接続に渡される SOCKADDR 構造体は、IPv4 マップの IPv6 アドレスである必要があります。 アプリケーションでは、これらの IPv4 マップ IPv6 アドレスを適切に処理し、デュアル スタック ソケットでのみ使用するように注意する必要があります。 IP アドレスを通常の IPv4 ソケットに渡す場合、アドレスは IPv4 マップ IPv6 アドレスではなく通常の IPv4 アドレスである必要があります。

Dual-Stack ソケットの使用に関する潜在的な問題

アプリケーションの潜在的な落とし穴は、デュアルスタック ソケットで IPv4 マップされた IPv6 アドレスを取得し、返された IP アドレスを別の IPv6 のみのソケットで使用しようとすることです。 たとえば、getsockname または getpeername 関数は、デュアルスタック ソケットで使用すると、IPv4 マップの IPv6 アドレスを返すことができます。 その後、返された IPv4 マップ IPv6 アドレスがデュアル スタック (ソケット作成時の既定の動作である IPv6 専用ソケット) に設定されていない別のソケットで使用される場合、IPv4 マップの IPv6 アドレスを持つこの IPv6 のみのソケットの使用は失敗します。 IPv4 マップの IPv6 アドレス形式は、デュアル スタック ソケットでのみ使用できます。

デュアルスタック・データグラム・ソケットで、アプリケーションが IPv4 経由で受信したデータグラムの WSAMSG 構造体でパケット情報を戻すために LPFN_WSARECVMSG (WSARecvMsg) 関数を必要とする場合は、ソケットでソケット・オプション IP_PKTINFO true に設定する必要があります。 ソケットで IPV6_PKTINFO オプションのみが true に設定されている場合、IPv6 経由で受信したデータグラムに対してパケット情報が提供されますが、IPv4 経由で受信したデータグラムには提供されない場合があります。

アプリケーションがデュアルスタック・データグラム・ソケットで IP_PKTINFO ソケット・オプションを設定しようとして、システムで IPv4 が使用不可になっている場合、setsockopt 関数は失敗し、WSAGetLastErrorは WSAEINVAL エラーで戻ります。 この同じエラーは、他のエラーの結果として、setsockopt 関数によっても返されます。 アプリケーションがデュアル スタック ソケットでIPPROTO_IP レベルのソケット オプションを設定しようとして、WSAEINVAL 失敗した場合、アプリケーションはローカル コンピューターで IPv4 が無効になっているかどうかを判断する必要があります。 IPv4 が有効または無効になっているかどうかを検出するために使用できる方法の 1 つは、af パラメーターをAF_INETに設定して IPv4 ソケットを作成 ソケット 関数を呼び出す方法です。 ソケット 関数が失敗し、WSAGetLastError が WSAEAFNOSUPPORT のエラー返した場合は、IPv4 が有効になっていないことになります。 この場合、IP_PKTINFO ソケット オプションを設定しようとしたときに、setsockopt 関数の失敗は、アプリケーションによって無視される可能性があります。 それ以外の場合は、IP_PKTINFO ソケット オプションを設定しようとしたときにエラーが予期しないエラーとして扱われる必要があります。

WSASendMsg 関数を使用してデータグラムを送信し、アプリケーションで使用する特定のローカル IP ソース アドレスを指定する場合、デュアルスタック ソケットの場合、これを処理する方法は宛先 IP アドレスによって異なります。 IPv4 宛先アドレスまたは IPv4 マップト IPv6 宛先アドレスに送信する場合、lpMsg パラメーターが指す WSAMSG 構造体で渡される制御データ・オブジェクトの 1 つに、送信に使用するローカル IPv4 ソース・アドレスを含む in_pktinfo 構造が含まれている必要があります。 IPv4 マップト IPv6 アドレスではない IPv6 宛先アドレスに送信する場合、lpMsg パラメーターが指す WSAMSG 構造体で渡される制御データ・オブジェクトの 1 つに、送信に使用するローカル IPv6 ソース・アドレスを含む in6_pktinfo 構造が含まれている必要があります。

IPv6 Guide for Windows Sockets Applications

IPv6 Winsock アプリケーションのデータ構造の変更

IPv6 Winsock アプリケーションの 関数呼び出し

ハードコーディングされた IPv4 アドレスの使用

IPv6 Winsock アプリケーションの ユーザー インターフェイスの問題

IPv6 Winsock アプリケーションの基になるプロトコルの

getpeernameする

getsockname

in_pktinfo

in6_pktinfo

IP_PKTINFO

IPV6_PKTINFO

setsockopt

LPFN_WSARECVMSG (WSARecvMsg)

WSASendMsg