プログラミングインタフェース

ホスト名とサービス名

インタフェース getaddrinfo(3SOCKET)getnameinfo(3SOCKET)gai_strerror(3SOCKET)、および freeaddrinfo(3SOCKET) を使用すると、ホスト上のサービスの名前とアドレスを簡単に変換できます。これらは、getipnodebyname(3SOCKET)gethostbyname(3NSL)、および getservbyname(3SOCKET) の API よりも新しいインタフェースです。IPv6 アドレスと IPv4 アドレスは、どちらも透過的に処理されます。

getaddrinfo(3SOCKET) ルーチンは、指定されたホスト名とサービス名に結合アドレスとポート番号を返します。getaddrinfo(3SOCKET) が返す情報は動的に割り当てられるので、この情報は freeaddrinfo(3SOCKET) を使用して解放し、メモリーリークを回避する必要があります。getnameinfo(3SOCKET) は、指定されたアドレスとポート番号に関連付けられたホスト名とサービス名を返します。gai_strerror(3SOCKET) を呼び出すと、getaddrinfo(3SOCKET)getnameinfo(3SOCKET) から返される EAI_xxx コードに基づくエラーメッセージが出力されます。

次に、getaddrinfo(3SOCKET) の使用例を示します。

struct addrinfo        *res, *aip;
struct addrinfo        hints;
int                    error;

/* Get host address.  Any type of address will do. */
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);
}