以下は、JM Projectからの引用である。
getaddrinfo(3) 関数は、4 つの関数 getipnodebyname(3), getipnodebyaddr(3), getservbyname(3), getservbyport(3) の 機能をまとめて一つのインターフェースにしたものである。 getaddrinfo(3) 関数はスレッドセーフで、ひとつ以上のソケットアドレス構造体を生成する。 この構造体は bind(2) や connect(2) などの関数コールでクライアント用・サーバー用のソケットを生成する際に 用いることができる。
上記のように、tcpv6c.cで使われているgetaddrinfo関数は、tcpc.cで使われているgethostbyname関数、getservbyname関数 という二つの関数の機能をまとめたものである。この、getaddrinfo関数を使用することにより処理を簡単に済ませている。 さらに、このgetaddrinfo関数は、IPv4アドレス構造体だけではなく、IPv6のサポートされているシステムならIPv6のソケッ トアドレス構造体を生成することもできる。 以上のように、getaddrinfo関数を使うことにより、IPv4、IPv6両方に対応し、より簡潔にプログラムを記述することができる。
IPv4 から IPv6 への移行を容易にするため、IPv6 プロトコル仕様ではIPv6アドレスの下位32ビットにIPv4 アドレスを埋め込んだ、2種類のグローバルIPv6アドレスを定義している。この仕様のために、IPv4でも通信する ことができる。 getaddrinfo関数は、上記の二つのグローバルIPv6アドレスのうちIPv4射影アドレスを返すため、tcpv6sはAF_INET6 でソケットをオープンしているにも関わらず、IPv4でも通信することが出来る。
IPv4射影アドレス
IPv4射影IPv6アドレスとは、 IPv6アドレスの上位80bitに0、81〜96bit目に1を入れ、下位32bitにIPv4アドレスを 埋め込んだアドレスである。IPv6をサポートしていないノードのアドレスをIPv6アドレスとして表現するために用 いられている。
source code file
ipv4_v6_c.c事前にサーバーをポート指定なしで起動し、次にクライアントをIPv6アドレスを用いて起動すると次のように 表示され、サーバーに上手く接続できていることが確認できる。
[ipv6 : 12/19 17:41] ./ipv4_v6_c 2001:02f8:001c:d048:0211:24ff:fe94:e040 connected to '2001:2f8:1c:d048:211:24ff:fe94:e040' by IPv6 trying 2001:2f8:1c:d048:211:24ff:fe94:e040 port 5320 Hello 2001:2f8:1c:d048:211:24ff:fe94:e040
次にポート指定ありで実行すると次のように表示された。
[ipv6 : 12/19 17:45] ./ipv4_v6_c 2001:02f8:001c:d048:0211:24ff:fe94:e040 3333 connected to '2001:2f8:1c:d048:211:24ff:fe94:e040' by IPv6 trying 2001:2f8:1c:d048:211:24ff:fe94:e040 port 3333 Hello 2001:2f8:1c:d048:211:24ff:fe94:e040
では、IPv4アドレスでも上手く実行できるかを確認する。 結果は次のようになった。
[ipv6 : 12/19 17:45] ./ipv4_v6_c 133.13.59.19 3333 connected to '133.13.59.19' by IPv4 trying 133.13.59.19 port 3333 Hello ::ffff:133.13.59.19 [ipv6 : 12/19 17:46] ./ipv4_v6_c 133.13.59.19 connected to '133.13.59.19' by IPv4 trying 133.13.59.19 port 5320 Hello ::ffff:133.13.59.19