getnameinfo 函数 (ws2tcpip.h)
getnameinfo 函数提供与协议无关的名称解析,从地址到 ANSI 主机名,从端口号到 ANSI 服务名称。
语法
INT WSAAPI getnameinfo(
[in] const SOCKADDR *pSockaddr,
[in] socklen_t SockaddrLength,
[out] PCHAR pNodeBuffer,
[in] DWORD NodeBufferSize,
[out] PCHAR pServiceBuffer,
[in] DWORD ServiceBufferSize,
[in] INT Flags
);
参数
[in] pSockaddr
指向包含套接字地址和端口号的套接字地址结构的指针。 对于 IPv4,sa 参数指向sockaddr_in结构。 对于 IPv6,sa 参数指向sockaddr_in6结构。
[in] SockaddrLength
sa 参数指向的结构的长度(以字节为单位)。
[out] pNodeBuffer
指向用于保存主机名的 ANSI 字符串的指针。 成功后,主机名默认返回为完全限定的域名 (FQDN) 。 如果 主机 参数为 NULL,则表示调用方不希望接收主机名字符串。
[in] NodeBufferSize
主机参数指向的缓冲区的长度(以字节为单位)。 调用方必须提供足够大的缓冲区来保存主机名,包括终止 NULL 字符。
[out] pServiceBuffer
指向用于保存服务名称的 ANSI 字符串的指针。 成功后,将返回一个 ANSI 字符串,表示与端口号关联的服务名称。 如果 serv 参数为 NULL,则表示调用方不希望接收服务名称字符串。
[in] ServiceBufferSize
serv 参数指向的缓冲区的长度(以字节为单位)。 调用方必须提供足够大的缓冲区来保存服务名称,包括终止 NULL 字符。
[in] Flags
用于自定义 getnameinfo 函数处理的值。 请参阅“备注”部分。
返回值
成功后, getnameinfo 返回零。 任何非零返回值都表示失败,可以通过调用 WSAGetLastError 来检索特定的错误代码。
getnameinfo 函数返回的非零错误代码也映射到 Internet 工程任务组 (IETF) 建议概述的错误集。 下表列出了这些错误代码及其 WSA 等效项。 建议使用 WSA 错误代码,因为它们为 Winsock 程序员提供熟悉且全面的错误信息。
错误值 | WSA 等效项 | 说明 |
---|---|---|
EAI_AGAIN | WSATRY_AGAIN | 名称解析暂时失败。 |
EAI_BADFLAGS | WSAEINVAL | 一个或多个无效参数已传递到 getnameinfo 函数。 如果请求了主机名,但 hostlen 参数为零,或者请求了服务名称,但 servlen 参数为零,则返回此错误。 |
EAI_FAIL | WSANO_RECOVERY | 名称解析中发生不可恢复的失败。 |
EAI_FAMILY | WSAEAFNOSUPPORT | 不支持 sa 参数指向的套接字地址结构的 sa_family 成员。 |
EAI_MEMORY | WSA_NOT_ENOUGH_MEMORY | 内存分配失败。 |
EAI_NONAME | WSAHOST_NOT_FOUND | 请求了服务名称,但在 sa 参数指向的结构中找不到端口号,或者找不到与端口号匹配的服务名称。 NI_NAMEREQD已设置,并且无法找到主机名,或者 主机 和 serv 参数均为 NULL。 |
使用 gai_strerror 函数根据 getnameinfo 函数返回的 EAI 代码打印错误消息。 提供 gai_strerror 函数是为了符合 IETF 建议,但它不是线程安全的。 因此,建议使用传统的 Windows 套接字函数,例如 WSAGetLastError 。
此外,可以返回以下错误代码。
错误代码 | 含义 |
---|---|
如果 sa 参数为 NULL 或 salen 参数小于 IPv4 sockaddr_in 结构大小或 IPv6 sockaddr_in6结构所需的 长度,则返回此错误。 |
注解
getnameinfo 函数是提供与协议无关的名称解析的函数的 ANSI 版本。 getnameinfo 函数用于将套接字地址结构的内容转换为节点名称和/或服务名称。
对于 IPv6 和 IPv4 协议,可以通过域名系统 (DNS) 、本地 主机 文件或其他命名机制进行名称解析。 此函数可用于确定 IPv4 或 IPv6 地址的主机名、反向 DNS 查找或确定端口号的服务名称。 getnameinfo 函数还可用于将 sockaddr 结构中的 IP 地址或端口号转换为 ANSI 字符串。 此函数还可用于确定主机名的 IP 地址。
另一个可用于 getnameinfo 函数的名称是 GetNameInfoA。 Ws2tcpip.h 头文件中的宏将 GetNameInfoA 定义为 getnameinfo。
此函数的 Unicode 版本在 Windows XP 上可用,Service Pack 2 (SP2) 及更高版本为 GetNameInfoW。
Winsock 头文件中的宏定义了一个混合大小写的 GetNameInfo 函数名称,当应用程序面向具有 SP2 及更高版本 (_WIN32_WINNT >= 0x0502) 的 Windows XP 时,可以使用该名称。 应使用 TCHAR 类型的指针的 host 和 serv 参数调用此 GetNameInfo 函数。 如果未定义 UNICODE 或 _UNICODE,则会将 GetNameInfo 定义为 ANSI 版本,并使用 char 类型的指针的 host 和 serv 参数调用 getnameinfo。 定义 UNICODE 或 _UNICODE 时,会将 GetNameInfo 定义为 Unicode 版本,并使用 PWCHAR 类型指针的 pNodeBuffer 和 pServiceBuffer 参数调用 GetNameInfoW。
为了简化确定 主机 和 serv 参数的缓冲区要求, Ws2tcpip.h 头文件中定义了以下最大主机名长度和最大服务名称的值。
#define NI_MAXSERV 32
#define NI_MAXHOST 1025
flags 参数可用于自定义 getnameinfo 函数的处理。 以下标志可用:
- NI_NOFQDN
- NI_NUMERICHOST
- NI_NAMEREQD
- NI_NUMERICSERV
- NI_DGRAM
设置 NI_NAMEREQD 标志时,DNS 无法解析的主机名将导致错误。
设置 NI_NOFQDN 标志会导致本地主机在 主机参数中 仅返回其相对可分辨名称 (RDN) 。
设置 NI_NUMERICHOST 标志将返回主机名的数值形式,而不是其名称。 如果 DNS 无法解析主机名,则还会返回主机名的数值形式。
设置 NI_NUMERICSERV 标志将返回服务的端口号,而不是其名称。 此外,如果找不到 ip 地址 (127.0.0.2 的主机名(例如) ),则主机名将作为 IP 地址返回。
在 Windows Vista 及更高版本中,如果未在 flags 参数中指定NI_NUMERICSERV,并且 sa 参数指向的 sockaddr 结构中包含的端口号未解析为已知服务,则 getnameinfo 函数将返回服务地址的数值形式 (端口号) 作为数字字符串。 指定 NI_NUMERICSERV 时,端口号将作为数字字符串返回。 RFC 3493 第 6.2 节中指定了此行为。 有关详细信息,请参阅 www.ietf.org/rfc3493.txt
在 Windows Server 2003 及更早版本中,如果未在 flags 参数中指定NI_NUMERICSERV,并且 sa 参数指向的 sockaddr 结构中包含的端口号未解析为已知服务,则 getnameinfo 函数将失败。 指定 NI_NUMERICSERV 时,端口号将作为数字字符串返回。
设置 NI_DGRAM 标志指示服务是数据报服务。 对于为 UDP 和 TCP 服务提供不同端口号的少数服务,此标志是必需的。
示例代码
下面的代码示例演示如何使用 getnameinfo 函数。#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
// link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int __cdecl main(int argc, char **argv)
{
//-----------------------------------------
// Declare and initialize variables
WSADATA wsaData = {0};
int iResult = 0;
DWORD dwRetval;
struct sockaddr_in saGNI;
char hostname[NI_MAXHOST];
char servInfo[NI_MAXSERV];
u_short port = 27015;
// Validate the parameters
if (argc != 2) {
printf("usage: %s IPv4 address\n", argv[0]);
printf(" to return hostname\n");
printf(" %s 127.0.0.1\n", argv[0]);
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
//-----------------------------------------
// Set up sockaddr_in structure which is passed
// to the getnameinfo function
saGNI.sin_family = AF_INET;
saGNI.sin_addr.s_addr = inet_addr(argv[1]);
saGNI.sin_port = htons(port);
//-----------------------------------------
// Call getnameinfo
dwRetval = getnameinfo((struct sockaddr *) &saGNI,
sizeof (struct sockaddr),
hostname,
NI_MAXHOST, servInfo, NI_MAXSERV, NI_NUMERICSERV);
if (dwRetval != 0) {
printf("getnameinfo failed with error # %ld\n", WSAGetLastError());
return 1;
} else {
printf("getnameinfo returned hostname = %s\n", hostname);
return 0;
}
}
在较旧版本的 Windows 上支持 getnameinfo
getnameinfo 函数已添加到 Windows XP 及更高版本的 Ws2_32.dll。 如果要在早期版本的 Windows (Windows 2000、Windows NT 和 Windows Me/98/95) 上使用此函数执行应用程序,则需要包含 Ws2tcpip.h 文件,同时包括 Wspiapi.h 文件。 添加 Wspiapi.h 包含文件时, getnameinfo 函数将定义为 Wspiapi.h 文件中的 WspiapiGetNameInfo 内联函数。 在运行时,WspiapiGetNameInfo 函数的实现方式如下:如果 Ws2_32.dll 或 Wship6.dll (包含适用于 Windows 2000) 的 IPv6 技术预览版中的 getnameinfo 的文件不包括 getnameinfo,则会根据 Wspiapi.h 头文件中的代码内联实现 getnameinfo 的版本。 此内联代码将用于本机不支持 getnameinfo 函数的旧 Windows 平台。安装适用于 Windows 2000 的 IPv6 技术预览版后,Windows 2000 支持 IPv6 协议。 否则,对早于 Windows XP 的 Windows 版本的 getnameinfo 支持仅限于处理 IPv4 名称解析。
GetNameInfoW 函数是 getnameinfo 的 Unicode 版本。 GetNameInfoW 函数已添加到 Windows XP SP2 中的Ws2_32.dll。 GetNameInfoW 函数不能用于早于带 SP2 的 Windows XP 的 Windows 版本。
Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。
Windows 8.1和Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 8.1、Windows Vista [桌面应用 |UWP 应用] |
最低受支持的服务器 | Windows Server 2003 [桌面应用 | UWP 应用] |
目标平台 | Windows |
标头 | ws2tcpip.h |
Library | Ws2_32.lib |
DLL | Ws2_32.dll |