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 Engineering Task Force (IETF 所概述的錯誤集) 建議。 下表列出這些錯誤碼及其 WSA 對等專案。 建議使用 WSA 錯誤碼,因為它們為 Winsock 程式設計人員提供熟悉且完整的錯誤資訊。
錯誤值 | WSA 對等專案 | Description |
---|---|---|
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 Sockets 函式,例如 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) 。 此 GetNameInfo 函式應該使用 TCHAR 類型指標的 host 和 serv 參數呼叫。 未定義 UNICODE 或_UNICODE時,GetNameInfo 會定義為 ANSI 版本,並使用char 類型的指標主機和 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 200) 0 Technical Preview 中的 getnameinfo 檔案不包含 getnameinfo,則 getnameinfo 版本會根據 Wspiapi.h 頭檔中的程式代碼內嵌實作。 此內嵌程式代碼將用於原本不支援 getnameinfo 函式的舊版 Windows 平臺上。安裝適用於 Windows 2000 的 IPv6 技術預覽版時,Windows 2000 支援 IPv6 通訊協定。 否則,在 Windows XP 之前的 Windows 版本上, getnameinfo 支援僅限於處理 IPv4 名稱解析。
GetNameInfoW 函式是 getnameinfo 的 Unicode 版本。 GetNameInfoW 函式已新增至 Windows XP SP2 中的 Ws2_32.dll。 GetNameInfoW 函式不能用於 Windows XP 與 SP2 之前的 Windows 版本。
Windows Phone 8:Windows Phone 8 和更新版本上的 Windows Phone Store 應用程式支援此函式。
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 |
程式庫 | Ws2_32.lib |
Dll | Ws2_32.dll |