getaddrinfo 是什么?

getaddrinfo 是一个用于将主机名和服务名解析为套接字地址结构的函数,它在网络编程中起着关键作用。以下是关于 getaddrinfo 函数的一些关键点:

  1. 协议无关性getaddrinfo 是一个协议无关的函数,既可以用于IPv4也可用于IPv6,这使得它比早期的 gethostbyname 函数更加灵活和强大。

  2. 功能:该函数能够处理名字到地址以及服务到端口这两种转换,返回的是一个 addrinfo 结构体(列表)指针,而不是单一的地址。

  3. 参数

    • nodename:可以是主机名或者数字化的地址字符串(IPv4的点分十进制串或者IPv6的16进制串)。
    • servname:服务名可以是十进制的端口号,也可以是已定义的服务名称,如"ftp"、"http"等。
    • hints:是一个 addrinfo 结构体的指针,由调用者填写关于期望返回的信息类型的提示。
    • res:返回结果,指向一个 addrinfo 结构体链表的指针。
  4. 返回值:成功时返回0,失败时返回非0错误码,可以通过 gai_strerror 函数获取错误信息。

  5. 使用细节:如果函数返回成功,那么 res 参数指向的变量将被填入一个指针,指向由 ai_next 成员串联起来的 addrinfo 结构链表。可能返回多个 addrinfo 结构的情况包括:与 hostname 参数关联的地址有多个,或者 service 参数指定的服务支持多个套接口类型。

  6. 内存管理:由 getaddrinfo 返回的所有存储空间都是动态分配的,必须通过调用 freeaddrinfo 函数释放。

  7. 应用场景getaddrinfo 在网络编程中有广泛的应用,包括建立TCP/UDP连接、实现DNS查询、处理多IP地址等。

综上所述,getaddrinfo 是一个功能全面、支持多种协议的地址解析函数,适用于现代网络编程中的多种场景。

getaddrinfo 函数的使用涉及到几个步骤,包括设置 hints 结构体、调用 getaddrinfo 函数、处理返回的 addrinfo 结构体链表,以及释放内存。下面是一个使用 getaddrinfo 函数的简单示例,它展示了如何将主机名和端口号解析为套接字地址结构:

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main() {
    const char *node = "example.com";
    const char *service = "http";
    struct addrinfo hints, *res, *p;

    // 初始化 hints 结构体
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;    // 不指定是IPv4还是IPv6
    hints.ai_socktype = SOCK_STREAM; // 我们想要的是流式套接字(例如TCP)

    // 调用 getaddrinfo 函数
    int status = getaddrinfo(node, service, &hints, &res);
    if (status != 0) {
        std::cerr << "getaddrinfo error: " << gai_strerror(status) << std::endl;
        return 1;
    }

    // 遍历 addrinfo 结构体链表
    for (p = res; p != NULL; p = p->ai_next) {
        void *addr;
        char ipstr[INET6_ADDRSTRLEN]; // INET6_ADDRSTRLEN 是 IPv6 地址的最大长度

        if (p->ai_family == AF_INET) { // IPv4
            struct sockaddr_in *ipv4 = reinterpret_cast<struct sockaddr_in *>(p->ai_addr);
            addr = &(ipv4->sin_addr);
        } else { // IPv6
            struct sockaddr_in6 *ipv6 = reinterpret_cast<struct sockaddr_in6 *>(p->ai_addr);
            addr = &(ipv6->sin6_addr);
        }

        // 将地址转换成字符串形式
        inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
        std::cout << "IP Address: " << ipstr << std::endl;
    }

    // 释放 getaddrinfo 分配的内存
    freeaddrinfo(res);

    return 0;
}

步骤解释:

  1. 初始化 hints 结构体

    • memset(&hints, 0, sizeof hints);:将 hints 结构体清零。
    • hints.ai_family = AF_UNSPEC;:不指定地址族,可以是IPv4或IPv6。
    • hints.ai_socktype = SOCK_STREAM;:指定我们想要的是流式套接字(例如TCP)。
  2. 调用 getaddrinfo 函数

    • getaddrinfo(node, service, &hints, &res);:将主机名和端口号解析为套接字地址结构。
    • 如果返回值不为0,则输出错误信息并退出。
  3. 遍历 addrinfo 结构体链表

    • 使用 for 循环遍历返回的 addrinfo 结构体链表。
    • 根据地址族(IPv4或IPv6),将地址转换为字符串形式,并输出。
  4. 释放内存

    • 使用 freeaddrinfo(res); 释放 getaddrinfo 分配的内存。

这个示例展示了如何使用 getaddrinfo 函数将主机名和端口号解析为套接字地址结构,并输出解析后的IP地址。希望这个示例能帮助你理解 getaddrinfo 的使用方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值