getaddrinfo 子例程

用途

与协议无关的主机名到地址转换。

库 (libc.a)

语法

#include <sys/socket.h>
#include <netdb.h>
int getaddrinfo (hostname, servname, hints, res)
const char *hostname;
const char *servname;
const struct addrinfo *hints;
struct addrinfo **res;

描述

hostnameservname 参数描述要引用的主机名和/或服务名称。 零个或其中一个自变量可能为 NULL。 非 NULL 主机名可以是主机名或数字主机地址字符串 (对于 IPv4 为点分十进制,对于 IPv6为十六进制)。 非 NULL 服务名称可以是服务名称或十进制端口号。

hints 参数指定有关所需返回信息的提示。 hostnameservname 参数是指向以 null 结束的字符串或 NULL 的指针。 其中一个或两个自变量必须是非 NULL 指针。 在正常客户机方案中,同时指定了 hostnameservname 参数。 在正常服务器方案中,仅指定 servname 参数。 非 NULL 主机名字符串可以是主机名或数字主机地址字符串 (例如,点分十进制 IPv4 地址或 IPv6 十六进制地址)。 非 NULL servname 字符串可以是服务名称或十进制端口号。

调用者可以选择性地传递由 hints 参数指向的 addrinfo 结构,以提供有关调用者支持的套接字类型的提示。 在此 提示 结构中,除 ai_flagsai_eflags ai_familyai_socktype以外的所有成员。 并且 ai_protocol 必须为零或 NULL 指针。 对于 ai_family , PF_UNSPEC 值表示调用者将接受任何协议系列。 ai_socktype 的值为零表示调用者接受任何套接字类型。 ai_protocol 的值为零表示调用者接受任何协议。 例如,如果调用者仅处理 TCP 而不是 UDP ,那么在调用 getaddrinfo 子例程时,应该将 hints 结构的 ai_socktype 成员设置为 SOCK_STREAM。 如果调用者仅处理 IPv4 而不处理 IPv6,那么在调用 getaddrinfo 时,应该将 hints 结构的 ai_family 成员设置为 PF_INET。 如果 getaddrinfo 中的 hints 参数是 NULL 指针,那么与调用者在将 ai_family 设置为 PF_UNSPEC 的情况下填充初始化为零的 addrinfo 结构相同。

成功返回时,将通过 res 参数返回指向一个或多个 addrinfo 结构的链接列表的指针。 调用者可以通过遵循 ai_next 指针来处理此列表中的每个 addrinfo 结构,直到迂到 NULL 指针为止。 在每个返回的 addrinfo 结构中,三个成员 ai_familyai_socktype, 而 ai_protocol 是调用 socket 子例程的相应自变量。 在每个 addrinfo 结构中, ai_addr 成员指向其长度由 ai_addrlen 成员指定的文件插入套接字地址结构。

如果在 hints 结构的 ai_flags 成员中设置了 AI_PASSIVE 位,那么调用者计划在对 bind 子例程的调用中使用返回的套接字地址结构。 如果 hostname 参数是 NULL 指针,那么对于 IPv4 地址,套接字地址结构的 IP 地址部分将设置为 INADDR_ANY ,对于 IPv6 地址,将设置为 IN6ADDR_ANY_INIT 。

如果未在提示结构的 ai_flags 成员中设置 AI_PASSIVE 位,那么返回的套接字地址结构已准备好调用 connect 子例程 (用于面向连接的协议) 或 connectsendtosendmsg 子例程 (对于无连接协议)。 如果 hostname 参数是 NULL 指针,那么套接字地址结构的 IP 地址部分将设置为回送地址。

如果在提示结构的 ai_flags 成员中设置了 AI_CANONNAME 位,那么成功返回后,链接列表中第一个 addrinfo 结构的 ai_canonname 成员将指向包含指定主机名的规范名称的以 NULL 结束的字符串。

如果指定了 AI_NUMERICHOST 标志,那么提供的非 NULL 节点名字符串是数字主机地址字符串。 否则,将返回 (EAI_NONAME) 错误。 此标志阻止调用任何类型的名称解析服务 (例如 DNS)。

如果指定了 AI_NUMERICSERV 标志,那么提供的非 NULL servname 字符串是数字端口字符串。 否则,将返回 (EAI_NONAME) 错误。 此标志可防止调用任何类型的名称解析服务。

如果 AI_V4MAPPED 标志与 AF_INET6的 ai_family 值一起指定, 当找不到匹配的 IPv6 地址 (ai_addrlen 为 16) 时, getaddrinfo 子例程返回 IPv4-mapped IPv6 地址。 例如,使用 DNS 时,如果找不到 AAAA 或 A6 记录,那么将对 A 记录进行查询。 任何找到的地址都将作为 IPv4-mapped IPv6 地址返回。 除非 ai_family 等于 AF_INET6,否则将忽略 AI_V4MAPPED 标志。

如果 AI_ALL 标志与 AI_V4MAPPED 标志一起使用,那么 getaddrinfo 子例程将返回所有匹配的 IPv6 和 IPv4 地址。 例如,使用 DNS 时,将首先对 AAAA/A6 记录进行查询。 如果成功,那么将返回这些 IPv6 地址。 对 A 记录进行了另一个查询,找到的任何 IPv4 地址都将作为 IPv4-mapped IPv6 地址返回。 将忽略不带 AI_V4MAPPED 标志的 AI_ALL 标志。
注: 当未指定 ai_family (AF_UNSPEC) 时,如果支持 AF_INET6 ,那么将使用 AI_V4MAPPED 和 AI_ALL 标志。

如果在提示结构的 ai_flags 成员中指定了 AI_EXTFLAGS ,并且将 ai_eflags 指定为非零值,那么地址选择算法将受影响。 地址选择算法使用一组有序规则 (RFC 3484) 对返回的 addrinfo 结构列表进行排序,同时考虑每个 addrinfo 结构的 ai_addr 成员中包含的地址以及可从中访问此地址的源地址。 ai_eflags 表示首选项,意味着如果更高的规则之前没有对地址集进行排序,那么将应用下面描述的规则。

可以将 ai_eflags 设置为以下标志的组合:

  • IPV6_PREFER_SRC_HOME: 首选可从家庭源地址访问的地址
  • IPV6_PREFER_SRC_COA: 首选可从 Care-of 源地址访问的地址
  • IPV6_PREFER_SRC_TMP: 首选可从临时地址访问的地址
  • IPV6_PREFER_SRC_PUBLIC: 可从公共源地址访问的首选地址
  • IPV6_PREFER_SRC_CGA: 可从加密生成的地址 (CGA) 源地址访问的首选地址
  • IPV6_PREFER_SRC_NONCGA: 可从非 CGA 源地址访问的首选地址

例如, IPV6_PREFER_SRC_TMP ai_eflags 表示地址选择算法将对返回的具有可从临时地址访问的地址的 addrinfo 结构进行排序,在可能的情况下,对具有可从公共地址访问的地址的结构进行排序。 同时设置矛盾标志 (例如 IPV6_PREFER_SRC_TMP 和 IPV6_PREFER_SRC_PUBLIC) 会导致错误 EINVAL。

如果指定了 AI_ADDRCONFIG 标志,那么仅当节点至少配置了一个 IPv6 源地址时,才应查询 AAAA 或 A6 记录。 仅当节点至少配置了一个 IPv4 源地址时,才应该对 A 记录进行查询。 回送地址被视为无效,无法作为已配置的源地址。

getaddrinfo 子例程返回的所有信息都是动态分配的: addrinfo 结构,套接字地址结构和 addrinfo 结构指向的规范主机名字符串。 要将此信息返回到系统,将调用 freeaddrinfo 子例程。

addrinfo 结构定义为:

struct addrinfo {
  int               ai_flags;          /* AI_PASSIVE, AI_CANONNAME */
  int               ai_family;         /* PF_xxx */
  int               ai_socktype;       /* SOCK_xxx */
  int               ai_protocol;       /* 0 or IP=PROTO_xxx for IPv4 and IPv6 */
  size_t            ai_addrlen;        /* length of ai_addr */
  char              *ai_canonname;     /* canoncial name for hostname */
  struct sockaddr   *ai_addr;          /* binary address */
  struct addrinfo   *ai_next;          /* next structure in linked list */
  int ai_eflags; /* Extended flags for special usage */
}

返回值

如果查询成功,那么将通过 res 参数返回指向一个或多个 addrinfo 结构的链接列表的指针。 零返回值表示成功。 如果查询失败,那么将返回非零错误代码。

错误代码

以下名称是非零错误代码。 请参阅 netdb.h 以获取进一步定义。

描述
EAI_ADDRFAMILY 主机名的地址系列不受支持
又是EAI_起 名称解析中发生临时故障
EAI_BADFLAGS ai_flags 的值无效
EAI_FAIL 名称解析中发生不可恢复故障
EAI_FAMILY ai_family 不受支持
EAI_MEMORY 内存分配失败
EAI_NODATA 没有与 hostname 关联的地址
EAI_NONAME 未提供 hostnameservname ,或未知
EAI_SERVICE ai_socktype 不支持 servname
EAI_SOCKTYPE ai_socktype 不受支持
EAI_SYSTEM errno 中返回了系统错误
eai_badextflags ai_eflags 的值无效。