IPv6 Winsock アプリケーションのデータ構造の変更
IPv6 のサポートを追加するときは、アプリケーションで適切なサイズのデータ構造が定義されていることを確認する必要があります。 IPv6 アドレスのサイズは、IPv4 アドレスよりもはるかに大きくなります。 IP アドレスを格納するときに IPv4 アドレスのサイズを処理するようにハードコードされた構造は、アプリケーションで問題を引き起こすため、変更する必要があります。
ベスト プラクティス
構造のサイズを適切に設定するには、SOCKADDR_STORAGE 構造体を使用することをお勧めします。 SOCKADDR_STORAGE 構造体は、IP アドレスのバージョンに依存しません。 SOCKADDR_STORAGE 構造体を使用して IP アドレスを格納すると、1 つのコード ベースで IPv4 アドレスと IPv6 アドレスを適切に処理できます。
次の例は、付録 B にある Server.c ファイルからの抜粋であり、SOCKADDR_STORAGE 構造体の適切な使用方法を示しています。 この例で示されているように、この構造体は適切に使用されると、IPv4 または IPv6 アドレスはどちらも適切に処理されることに注意してください。
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#define BUFFER_SIZE 512
#define DEFAULT_PORT "27015"
int main(int argc, char **argv)
{
char Buffer[BUFFER_SIZE] = {0};
char *Hostname;
int Family = AF_UNSPEC;
int SocketType = SOCK_STREAM;
char *Port = DEFAULT_PORT;
char *Address = NULL;
int i = 0;
DWORD dwRetval = 0;
int iResult = 0;
int FromLen = 0;
int AmountRead = 0;
SOCKADDR_STORAGE From;
WSADATA wsaData;
ADDRINFO *AddrInfo = NULL;
ADDRINFO *AI = NULL;
// Parse arguments
if (argc >= 1) {
Hostname = argv[1];
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
From.ss_family = (ADDRESS_FAMILY) Family;
//...
return 0;
}
Note
SOCKADDR_STORAGE 構造体は、Windows XP の新機能です。
回避するコード
通常、多くのアプリケーションは、プロトコルに依存しないアドレスを格納するために sockaddr 構造体を使用し、IP アドレスの格納には sockaddr_in 構造体を使用します。 sockaddr 構造体も sockaddr_in 構造体も IPv6 アドレスを保持するのに十分な大きさがないため、アプリケーションを IPv6 互換にするにはどちらも不十分です。
コーディング タスク
既存のコード ベースを IPv4 から IPv4 と IPv6 の相互運用性に変更するには
- Checkv4.exe ユーティリティを取得します。 このユーティリティは、Microsoft Windows ソフトウェア開発キット (SDK) に含まれています。
- コードに対して Checkv4.exe ユーティリティを実行します。 ファイルに対して Checkv4.exe ユーティリティを実行する方法の詳細については、「Checkv4.exe ユーティリティの使用」のセクションを参照してください。
- このユーティリティは、sockaddr 構造体または sockaddr_in 構造体の使用を警告し、IPv6 互換構造体である SOCKADDR_STORAGE に置き換える方法について推奨事項を提供します。
- SOCKADDR_STORAGE 構造体を使用するには、このようなインスタンス、および必要な場合には関連するコードを置き換えます。
あるいは、コード ベースで sockaddr 構造体および sockaddr_in 構造体のインスタンスを検索し、そのような使用法 (および必要な場合にはその他の関連コード) をすべて SOCKADDR_STORAGE 構造体に変更することもできます。
Note
addrinfo 構造体および SOCKADDR_STORAGE 構造体には、プロトコルおよびアドレス ファミリ メンバー (ai_family および ss_family) がそれぞれ含まれます。 RFC 2553 では、addrinfo の ai_family メンバーは int として指定されていますが、ss_family は short として指定されています。そのため、これらのメンバー間で直接コピーすると、コンパイラ エラーが発生します。
関連トピック