WinSock gethostbyaddr

gethostbyaddrは、IPアドレスからホスト情報を取得する(逆引き)。

gethostbyaddr関数は以下のように定義されている

struct hostent FAR * PASCAL FAR gethostbyaddr(
        IN const char FAR * addr, //取得したいホスト情報のインターネットアドレス
        IN int len,               //インターネットアドレス長
        IN int type);             //アドレスファミリ(TCP/IPではAF_INET)


gethostbyaddr関数は失敗するとNULLポインタを返す。WSAGetLastError関数によって失敗した原因を調べることができる。

gethostbyaddr関数が失敗したときのWSAGetLsatErrorの値は以下の通り

戻り値説明
WSANOTINITIALISEDこの関数を使う前にWSAStartupの呼び出しを成功させておかなければならない
WSAENETDOWNネットワークサブシステムが停止している
WSAHOST_NOT_FOUND正式なホスト名が見つかりません
WSATRY_AGAIN正式でないホストが見つからない。または、サーバーが停止している
WSANO_RECOVERY回復不能なエラーが発生しました
WSANO_DATA要求されたホスト名は有効である、しかし要求された種類のデータは見つかりませんでした
WSAEINPROGRESSブロッキングWinSock1.1の呼び出しが現在進行中、またはサービスプロバイダーはまだコールバック関数を処理中です。
WSAEAFNOSUPPORT指定されたアドレスファミリ(type引数)は、WinSockの実装ではサポートされていません
WSAEFAULTname引数は、有効なユーザーアドレス空間の一部ではない
WSAEINTRブロッキングWinSock1.1の呼び出しは、WSACancelBlockingCallによってキャンセルされた。

戻り値の型であるstruct hostent構造体は、winsock.h に以下のように定義されている

struct  hostent {
        char    FAR * h_name;           /* official name of host */
        char    FAR * FAR * h_aliases;  /* alias list */
        short   h_addrtype;             /* host address type */
        short   h_length;               /* length of address */
        char    FAR * FAR * h_addr_list; /* list of addresses */
#define h_addr  h_addr_list[0]          /* address, for backward compat */
};


  • gethostbyaddrの使用例

  • はてな」のIPアドレスを逆引きする

    #include <stdio.h>
    #include <winsock.h>
    #pragma comment(lib, "wsock32.lib")
    
    void PrintHostent(LPHOSTENT lpHostEntry)
    {
        printf("HostName: %s\n", lpHostEntry->h_name);
        printf("h_length: %d\n", lpHostEntry->h_length);
        printf("h_addrtype: %s\n", 
            lpHostEntry->h_addrtype == AF_INET ? "AF_INET" : "Unknown address type");
    
        for (int i = 0; lpHostEntry->h_aliases[i] != NULL; i++) {
            printf("h_aliases[%d]: %s\n", i, lpHostEntry->h_aliases[i]);
        }
    
        for (int i = 0; lpHostEntry->h_addr_list[i] != NULL;i++) {
            LPIN_ADDR addr = (LPIN_ADDR)lpHostEntry->h_addr_list[i];
            printf("h_addr_list[%d]: %s\n", i, inet_ntoa(*addr));
        }
    }
    
    int main()
    {
        WSADATA wsaData;
        int nRet;
        LPHOSTENT lpHostEntry;
        char *lpIPAddress = "59.106.108.77";
        IN_ADDR addr;
    
        nRet = WSAStartup(MAKEWORD(1, 1), &wsaData);
        if (nRet != 0) {
            fprintf(stderr, "WSAStartup error: %d\n", WSAGetLastError());
            goto EXIT_FUNC;
        }
    
        addr.S_un.S_addr = inet_addr(lpIPAddress);
        if (addr.S_un.S_addr == INADDR_NONE) {
            fprintf(stderr, "inet_addr error\n");
            goto EXIT_FUNC;
        }
    
        lpHostEntry = gethostbyaddr((const char*)&addr, sizeof(struct in_addr), AF_INET);
        if (lpHostEntry != NULL) {
            PrintHostent(lpHostEntry);
        } else {
            switch (WSAGetLastError()) {
            case WSANOTINITIALISED:
                puts("WSANOTINITIALISED");
                break;
    
            case WSAENETDOWN:
                puts("WSAENETDOWN");
                break;
    
            case WSAHOST_NOT_FOUND:
                puts("WSAHOST_NOT_FOUND");
                break;
    
            case WSATRY_AGAIN:
                puts("WSATRY_AGAIN");
                break;
    
            case WSANO_RECOVERY:
                puts("WSANO_RECOVERY");
                break;
    
            case WSANO_DATA:
                puts("WSANO_DATA");
                break;
    
            case WSAEINPROGRESS:
                puts("WSAEINPROGRESS");
                break;
    
            case WSAEAFNOSUPPORT:
                puts("WSAEAFNOSUPPORT");
                break;
    
            case WSAEFAULT:
                puts("WSAEFAULT");
                break;
    
            case WSAEINTR:
                puts("WSAEINTR");
                break;
    
            default:
                puts("Other error");
                break;
            }
        }
    
    EXIT_FUNC:
        WSACleanup();
    
        return 0;
    }



    実行結果

    HostName: d.st-hatena.com
    h_length: 4
    h_addrtype: AF_INET
    h_addr_list[0]: 59.106.108.77