For the complete documentation index, see llms.txt. This page is also available as Markdown.

getaddrinfo(3)

getaddrinfo — 套接字地址结构与主机和服务名的转换

名称

getaddrinfo, freeaddrinfo

概要

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

int
getaddrinfo(const char *hostname, const char *servname,
    const struct addrinfo *hints, struct addrinfo **res);

void
freeaddrinfo(struct addrinfo *ai);

描述

getaddrinfo 函数用于获取主机 hostname 和服务 servname 的地址和端口号列表。它是 gethostbyname(3) 和 getservbyname(3) 函数的替代品,并提供更大的灵活性。

hostname 和 servname 参数要么是指向以 NUL 结尾的字符串的指针,要么是空指针。hostname 的可接受值可以是有效的主机名或由点分十进制 IPv4 地址、IPv6 地址或 UNIX 域地址组成的数字主机地址字符串。servname 可以是十进制端口号或 services(5) 中列出的服务名。hostname 和 servname 中至少有一个必须非空。

hints 是一个可选指针,指向 struct addrinfo,由 <netdb.h> 定义:

此结构可用于提供有关调用者支持或希望使用的套接字类型的提示。调用者可以在 hints 中提供以下结构元素:

AI_ADDRCONFIG 如果设置了 AI_ADDRCONFIG 位,则仅当本地系统上配置了 IPv4 地址时才返回 IPv4 地址,仅当本地系统上配置了 IPv6 地址时才返回 IPv6 地址。

AI_ALL 如果 AI_ALL 标志与 AI_V4MAPPED 标志一起使用,则 getaddrinfo 将返回所有匹配的 IPv6 和 IPv4 地址。例如,使用 DNS 时,将同时查询 AAAA 记录和 A 记录,getaddrinfo 返回两个查询的组合结果。找到的任何 IPv4 地址将作为 IPv4 映射的 IPv6 地址返回。不带 AI_V4MAPPED 标志的 AI_ALL 标志将被忽略。

AI_CANONNAME 如果设置了 AI_CANONNAME 位,则对 getaddrinfo 的成功调用将在返回的第一个 addrinfo 结构的 ai_canonname 元素中返回包含指定主机名规范名称的以 NUL 结尾的字符串。

AI_NUMERICHOST 如果设置了 AI_NUMERICHOST 位,则表示 hostname 应被视为定义 IPv4 或 IPv6 地址的数字字符串,不应尝试名称解析。

AI_NUMERICSERV 如果设置了 AI_NUMERICSERV 位,则提供的非空 servname 字符串应为数字端口字符串。否则,将返回 EAI_NONAME 错误。此位将阻止调用任何类型的名称解析服务(例如 NIS+)。

AI_PASSIVE 如果设置了 AI_PASSIVE 位,则表示返回的套接字地址结构旨在用于 bind(2) 调用。在这种情况下,如果 hostname 参数是空指针,则套接字地址结构的 IP 地址部分对于 IPv4 地址将设置为 INADDR_ANY,对于 IPv6 地址将设置为 IN6ADDR_ANY_INIT。如果未设置 AI_PASSIVE 位,则返回的套接字地址结构将准备好用于面向连接协议的 connect(2) 调用,或如果选择了无连接协议则用于 connect(2)、sendto(2) 或 sendmsg(2)。如果 hostname 是空指针且未设置 AI_PASSIVE,则套接字地址结构的 IP 地址部分将设置为回环地址。

AI_V4MAPPED 如果指定了 AI_V4MAPPED 标志且 ai_family 为 AF_INET6,则 getaddrinfo 在找不到匹配的 IPv6 地址时将返回 IPv4 映射的 IPv6 地址(ai_addrlen 将为 16)。例如,使用 DNS 时,如果未找到 AAAA 记录,则查询 A 记录,找到的任何记录将作为 IPv4 映射的 IPv6 地址返回。除非 ai_family 等于 AF_INET6,否则 AI_V4MAPPED 标志将被忽略。

ai_family 应使用的地址族。当 ai_family 设置为 AF_UNSPEC 时,表示调用者将接受操作系统支持的任何地址族。

ai_socktype 表示所需的套接字类型:SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET 或 SOCK_RAW。当 ai_socktype 为零时,调用者将接受任何套接字类型。

ai_protocol 表示所需的传输协议:IPPROTO_UDP、IPPROTO_TCP、IPPROTO_SCTP 或 IPPROTO_UDPLITE。如果 ai_protocol 为零,调用者将接受任何协议。

ai_flags hints 参数指向的 ai_flags 字段应设置为零,或为 AI_ADDRCONFIG、AI_ALL、AI_CANONNAME、AI_NUMERICHOST、AI_NUMERICSERV、AI_PASSIVE 和 AI_V4MAPPED 中一个或多个值的按位或。对于 UNIX 域地址,ai_flags 被忽略。

通过 hints 传递的 addrinfo 结构的所有其他元素必须为零或空指针。

如果 hints 是空指针,getaddrinfo 的行为如同调用者提供了一个 struct addrinfo,其中 ai_family 设置为 AF_UNSPEC,所有其他元素设置为零或 NULL。

成功调用 getaddrinfo 后,*res 是指向一个或多个 addrinfo 结构链表的指针。可以通过跟随每个 addrinfo 结构中的 ai_next 指针遍历列表,直到遇到空指针。每个返回的 addrinfo 结构包含三个适合 socket(2) 调用的成员:ai_family、ai_socktype 和 ai_protocol。对于列表中的每个 addrinfo 结构,ai_addr 成员指向一个长度为 ai_addrlen 的已填充套接字地址结构。

此 getaddrinfo 实现允许带范围标识的数字 IPv6 地址表示法,如 RFC 4007 第 11 章所述。通过在地址后附加百分号和范围标识,可以填充地址的 sin6_scope_id 字段。这使得范围地址的管理更加容易,并允许范围地址的剪切和粘贴输入。

目前代码仅支持使用此格式的链路本地地址。范围标识被硬编码为与链路关联的硬件接口的名称(如 ne0)。例如“fe80::1%ne0”,表示“与 ne0 接口关联的链路上的 fe80::1”。

当前实现假设接口与链路之间存在一对一关系,但规范中并不一定如此。

getaddrinfo 返回的所有信息都是动态分配的:addrinfo 结构本身以及 addrinfo 结构中包含的套接字地址结构和规范主机名字符串。

成功调用 getaddrinfo 创建的动态分配结构的内存由 freeaddrinfo 函数释放。ai 指针应为通过调用 getaddrinfo 创建的 addrinfo 结构。

实现注释

freeaddrinfo(NULL) 的行为在 -susv4 和 RFC 3493 中均未指定。当前实现忽略 NULL 参数,以兼容依赖其他操作系统实现细节的程序。

返回值

getaddrinfo 成功时返回零,出错时返回 gai_strerror(3) 中列出的错误代码之一。

实例

以下代码尝试通过流式套接字连接到“www.kame.net”的“http”服务。它遍历所有可用的地址,而不考虑地址族。如果目标解析为 IPv4 地址,将使用 AF_INET 套接字。类似地,如果解析为 IPv6,将使用 AF_INET6 套接字。注意,没有对特定地址族的硬编码引用。即使 getaddrinfo 返回非 IPv4/v6 的地址,代码也能工作。

以下示例尝试为所有可用的地址族打开通配监听套接字,用于“http”服务。

参见

bind(2), connect(2), send(2), socket(2), gai_strerror(3), gethostbyname(3), getnameinfo(3), getservbyname(3), resolver(3), inet(4), inet6(4), unix(4), hosts(5), resolv.conf(5), services(5), hostname(7), ip6addrctl(8)

R. Gilligan, S. Thomson, J. Bound, J. McCann, W. Stevens, "Basic Socket Interface Extensions for IPv6", February 2003.

S. Deering, B. Haberman, T. Jinmei, E. Nordmark, B. Zill, "IPv6 Scoped Address Architecture", March 2005.

Craig Metz, "Protocol Independence Using the Sockets API", Proceedings of the freenix track: 2000 USENIX annual technical conference, June 2000.

标准

getaddrinfo 函数由 IEEE Std 1003.1-2004("POSIX.1")规范定义,并记录在 RFC 3493“Basic Socket Interface Extensions for IPv6”中。

最后更新于

这有帮助吗?