C++ gethostbyname函数使用示例

**

gethostbyname函数

**

gethostbyname 函数主要功能是从主机数据库中检索与主机名对应的主机信息。

gethostbyname函数返回一个指向宿主结构的指针——宿主结构是由Windows Sockets分配的。主机结构包含成功搜索name参数中指定的主机的结果。

如果name参数中指定的主机同时具有IPv4地址和IPv6地址,则只返回IPv4地址。gethostbyname函数只能返回name参数对应的IPv4地址。如果主机需要IPv6地址,或者主机需要IPv4和IPv6地址,则应该使用getaddrinfo函数和相关的addrinfo结构。
如果name参数指向空字符串或name为NULL,则返回的字符串与成功调用gethostname函数(本地计算机的标准主机名)返回的字符串相同。

如果name参数包含合法IPv4地址的字符串表示形式,则在主机结构中返回表示该字符串的二进制IPv4地址。主机结构的h_name成员包含IPv4地址的字符串表示形式,h_addr_list包含二进制IPv4地址。如果name参数包含IPv6地址或非法IPv4地址的字符串表示形式,那么gethostbyname函数将失败并返回WSANO_DATA。

gethostbyname函数返回的宿主结构的内存是由Winsock DLL内部从线程本地存储中分配的。无论在线程上调用gethostbyaddr或gethostbyname函数多少次,只分配和使用一个宿主结构。如果要在同一线程上对gethostbyname或gethostbyaddr函数进行额外调用,则必须将返回的宿主结构复制到应用程序缓冲区中。否则,返回值将被同一线程上后续的gethostbyname或gethostbyaddr调用覆盖。为返回的宿主结构分配的内部内存在线程退出时由Winsock DLL释放。

应用程序不应该尝试释放返回的宿主结构所使用的内存。应用程序绝不能试图修改此结构或释放其任何组件。此外,每个线程只分配该结构的一个副本,因此应用程序应该在对gethostbyname或gethostbyaddr发出任何其他函数调用之前复制所需的任何信息。

gethostbyname函数不能将IP地址字符串作为名称传递给它的参数,并将其解析为主机名。这样的请求完全被视为传递的IPv4地址或未知主机名的字符串表示形式。应用程序可以使用inet_addr将IPv4地址字符串转换为二进制IPv4地址,然后使用另一个函数gethostbyaddr将IPv4地址解析为主机名。

windows系统演示示例:

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char** argv)
{

    //-----------------------------------------
    // 声明和初始化变量
    WSADATA wsaData;
    int iResult = 0;

    DWORD dwError = 0;
    int i = 0;

    struct hostent* remoteHost = nullptr;
    char* host_name = nullptr;
    struct in_addr addr;

    char** pAlias;

    // 验证参数
#ifndef _DEBUG
    if (argc != 2) {
        printf("usage: %s hostname\n", argv[0]);
        printf("  to return the IP addresses for the host\n");
        printf("       %s www.contoso.com\n", argv[0]);
        printf(" or\n");
        printf("       %s IPv4string\n", argv[0]);
        printf("  to return an IPv4 binary address for an IPv4string\n");
        printf("       %s 127.0.0.1\n", argv[0]);
        return 1;
    }
#endif
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }
#ifndef _DEBUG
    host_name = argv[1];
#else
    host_name = "www.baidu.com";
#endif
    printf("Calling gethostbyname with %s\n", host_name);
    remoteHost = gethostbyname(host_name);

    if (remoteHost == NULL) {
        dwError = WSAGetLastError();
        if (dwError != 0) {
            if (dwError == WSAHOST_NOT_FOUND) {
                printf("Host not found\n");
                return 1;
            } else if (dwError == WSANO_DATA) {
                printf("No data record found\n");
                return 1;
            } else {
                printf("Function failed with error: %ld\n", dwError);
                return 1;
            }
        }
    } else {
        printf("Function returned:\n");
        printf("\tOfficial name: %s\n", remoteHost->h_name);
        for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) {
            printf("\t别名 #%d: %s\n", ++i, *pAlias);
        }
        printf("\t地址类型: ");
        switch (remoteHost->h_addrtype) {
        case AF_INET:
            printf(" AF_INET \n");
            break;
        case AF_NETBIOS:
            printf(" AF_NETBIOS \n");
            break;
        default:
            printf(" %d\n", remoteHost->h_addrtype);
            break;
        }
        printf("\t地址长度: %d\n", remoteHost->h_length);

        i = 0;
        if (remoteHost->h_addrtype == AF_INET) {
            while (remoteHost->h_addr_list[i] != 0) {
                addr.s_addr = *(u_long*)remoteHost->h_addr_list[i++];
                printf("\tIP 地址 #%d: %s\n", i, inet_ntoa(addr));
            }
        } else if (remoteHost->h_addrtype == AF_NETBIOS) {
            printf("返回 NETBIOS 地址 \n");
        }
    }

    return 0;
}

输出结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗羊羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值