インタフェース getaddrinfo(3SOCKET)、getnameinfo(3SOCKET)、および freeaddrinfo(3SOCKE) を使用すると、ホスト上のサービスの名前とアドレスを簡単に変換できます。IPv6 の場合、getipnodebyname(3SOCKET) と getservbyname(3SOCKET) を呼び出す代わりに、これらのインタフェースを使用できます。同様に IPv4 でも、gethostbyname(3NSL) と getservbyname(3SOCKET) の代わりに、これらのインタフェースを使用できます。IPv6 アドレスと IPv4 アドレスは、どちらも透過的に処理されます。
getaddrinfo(3SOCKET) ルーチンは、指定されたホスト名とサービス名に結合アドレスとポート番号を返します。getaddrinfo(3SOCKET) が返す情報は動的に割り当てられるので、この情報は freeaddrinfo(3SOCKET) を使用して解放し、メモリーリークを回避する必要があります。getnameinfo(3SOCKET) は、指定されたアドレスとポート番号に関連付けられたホスト名とサービス名を返します。getaddrinfo(3SOCKET) と getnameinfo(3SOCKET) が返す EAI_xxx コードに基づくエラーメッセージを出力するには、gai_strerror(3SOCKET) を呼び出す必要があります。
次に、getaddrinfo(3SOCKET) の使用例を示します。
struct addrinfo *res, *aip; struct addrinfo hints; int sock = -1; int error; /* ホストアドレスを取得する。アドレスのタイプは任意 */ bzero(&hints, sizeof (hints)); hints.ai_flags = AI_ALL|AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(hostname, servicename, &hints, &res); if (error != 0) { (void) fprintf(stderr, "getaddrinfo: %s for host %s service %s\n", gai_strerror(error), hostname, servicename); return (-1); }
res が指す構造体の getaddrinfo(3SOCKET) が返す情報を処理したあと、freeaddrinfo(res) を使用して記憶領域を解放する必要があります。
次の例に示すように、getnameinfo(3SOCKET) ルーチンはエラーの原因を識別するときに特に便利です。
struct sockaddr_storage faddr; int sock, new_sock, sock_opt; socklen_t faddrlen; int error; char hname[NI_MAXHOST]; char sname[NI_MAXSERV]; ... faddrlen = sizeof (faddr); new_sock = accept(sock, (struct sockaddr *)&faddr, &faddrlen); if (new_sock == -1) { if (errno != EINTR && errno != ECONNABORTED) { perror("accept"); } continue; } error = getnameinfo((struct sockaddr *)&faddr, faddrlen, hname, sizeof (hname), sname, sizeof (sname), 0); if (error) { (void) fprintf(stderr, "getnameinfo: %s\n", gai_strerror(error)); } else { (void) printf("Connection from %s/%s\n", hname, sname); }