getaddrinfo

IPでの名前解決を行なうためにgethostbynameを使うのが一般的でしたが、IPv6の登場とともに、名前解決にgetaddrinfo()を使わなくてはならなくなってしまいました。 ここでは、WindowsとVC++という環境でgetaddrinfoを使った例を説明していきたいと思います。

準備

まず、winsock2の開発環境が新しい必要があります。 古いものだと、getaddrinfoとstruct addrinfoが入っていません。 また、winsock2を使うので、ws2_32.libにリンクする必要があります。

個人的にはWindowsXP以降のもの意外ではあまりgetaddrinfoを使おうと思いません。 というのも、IPv6が入っているのがWindowsXPからで、それより前ならばgethostbynameを使えばいいかなと思っているからです。 WindowsXPには、IPv6が入っていますが、初期状態ではEnableされていないのでIPv6を使うには、コマンドプロンプトで「ipv6 install」を実行してIPv6環境をEnableしなくてはなりません。 「ipv6 install」コマンドは一度行なえば何度リブートしても大丈夫です。 IPv6機能をDisableしたい場合には、「ipv6 uninstall」コマンドを実行してください。 「ipv6 install」を実行しなくてもgetaddrinfoを使えます。 ただし、IPv6アドレスの名前解決は出来ず、IPv4の名前解決だけになります。

すごく単純な例

とりあえず、簡単な例を書いてみます。 まずは、IPv4のみです。 しかも、文字列から32ビットのIPv4アドレス値を取得するというgethostbynameと同じ使い方ような使い方をしています。


#include <winsock2.h>
#include <ws2tcpip.h>

int
main()
{
 char *hostname = "localhost";
 struct addrinfo hints, *res;
 struct in_addr addr;
 int err;

 WSADATA data;
 WSAStartup(MAKEWORD(2,0), &data);

 memset(&hints, 0, sizeof(hints));
 hints.ai_socktype = SOCK_STREAM;
 hints.ai_family = AF_INET;

 if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
   printf("error %d\n", err);
   return 1;
 }

 addr.S_un = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.S_un;

 printf("ip address : %s\n", inet_ntoa(addr));

 freeaddrinfo(res);

 WSACleanup();

 return 0;
}

getaddrinfoで確保したメモリは、freeaddrinfoを使って開放します。 freeaddrinfoを使うのを結構忘れてしまうので、気をつけましょう。

プロフェッショナルIPv6解説動画シリーズ再生リスト

動画で学ぶ「プロフェッショナルIPv6」を作っています。 もしよろしければご覧ください。お楽しみいただければ幸いです!