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