使用 DnsQuery 函式,透過 Visual C++ .NET 解析主機名和主機名
本文提供 Win32 控制台應用程式範例,說明如何使用 函 DnsQuery
式來解析主機名和主機 IP。
原始產品版本: Winsock
原始 KB 編號: 831226
建立範例 Win32 控制台應用程式,說明如何使用 DnsQuery 函式
在 Winsock 中,使用函 getaddrinfo
式而非 getaddrbyname
函式來裝載應用程式中的名稱。 函 getaddrbyname
式已取代 getaddrinfo
為處理 IPv4 和 IPv6 尋址的函式。
Winsock 在 Windows Server 2003 中最近包含新版 getaddrinfo
函式之前,從未考慮過寬字元。 新版本名為 GetAddrInfo。 如果您需要所有 NT 型作業系統的解決方案,請使用 DNS 用戶端 DNSQuery 函式來解析主機名。 函 DNSQuery
式具有廣泛的版本,應該在 Windows 2000 和更新版本的作業系統Microsoft運作。
使用下列步驟來建立範例 Win32 控制台應用程式,說明如何使用 函 DnsQuery
式。 函 DnsQuery
式會將查詢傳送至 DNS 伺服器,以將主機名解析為 IP 位址,反之亦然。
開始Microsoft Visual Studio .NET。
在 [專案類型] 底下,按兩下 [Visual C++ 專案],然後按兩下 [範本] 底下的 [Win32 專案]。
在 [ 名稱 ] 方塊中輸入Q831226。
在 Win32 應用程式精靈中,按兩下 [控制台應用程式],按兩下 [空白專案],然後按兩下 [ 完成]。
在 方案總管 中,以滑鼠右鍵按兩下 [來源檔案],按兩下 [新增],然後按兩下 [新增專案]。 將C++檔案 (.cpp) 新增至專案。 將檔案 命名為 Q831226.cpp。
在Q831226.cpp檔案中貼上下列程序代碼:
#include <winsock2.h> //winsock #include <windns.h> //DNS api's #include <stdio.h> //standard i/o //Usage of the program void Usage(char *progname) { fprintf(stderr,"Usage\n%s -n [HostName|IP Address] -t [Type] -s [DnsServerIp]\n",progname); fprintf(stderr,"Where:\n\t\"HostName|IP Address\" is the name or IP address of the computer "); fprintf(stderr,"of the record set being queried\n"); fprintf(stderr,"\t\"Type\" is the type of record set to be queried A or PTR\n"); fprintf(stderr,"\t\"DnsServerIp\"is the IP address of DNS server (in dotted decimal notation)"); fprintf(stderr,"to which the query should be sent\n"); exit(1); } void ReverseIP(char* pIP) { char seps[] = "."; char *token; char pIPSec[4][4]; int i=0; token = strtok( pIP, seps); while( token != NULL ) { /* While there are "." characters in "string"*/ sprintf(pIPSec[i],"%s", token); /* Get next "." character: */ token = strtok( NULL, seps ); i++; } sprintf(pIP,"%s.%s.%s.%s.%s", pIPSec[3],pIPSec[2],pIPSec[1],pIPSec[0],"IN-ADDR.ARPA"); } // the main function void __cdecl main(int argc, char* argv[]) { DNS_STATUS status; //Return value of DnsQuery_A() function. PDNS_RECORD pDnsRecord; //Pointer to DNS_RECORD structure. PIP4_ARRAY pSrvList = NULL; //Pointer to IP4_ARRAY structure. WORD wType; //Type of the record to be queried. char* pOwnerName; //Owner name to be queried. char pReversedIP[255];//Reversed IP address. char DnsServIp[255]; //DNS server ip address. DNS_FREE_TYPE freetype; freetype = DnsFreeRecordListDeep; IN_ADDR ipaddr; if (argc > 4) { for (int i = 1; i < argc; i++) { if ((argv[i][0] == '-') || (argv[i][0] == '/')) { switch (tolower(argv[i][1])) { case 'n': pOwnerName = argv[++i]; break; case 't': if (!stricmp(argv[i + 1], "A")) wType = DNS_TYPE_A; //Query host records to resolve a name. else if (!stricmp(argv[i + 1], "PTR")) { //pOwnerName should be in "xxx.xxx.xxx.xxx" format if (strlen(pOwnerName) <= 15) { //You must reverse the IP address to request a Reverse Lookup //of a host name. sprintf(pReversedIP, "%s", pOwnerName); ReverseIP(pReversedIP); pOwnerName = pReversedIP; wType = DNS_TYPE_PTR; //Query PTR records to resolve an IP address } else { Usage(argv[0]); } } else Usage(argv[0]); i++; break; case 's': // Allocate memory for IP4_ARRAY structure. pSrvList = (PIP4_ARRAY)LocalAlloc(LPTR, sizeof(IP4_ARRAY)); if (!pSrvList) { printf("Memory allocation failed \n"); exit(1); } if (argv[++i]) { strcpy(DnsServIp, argv[i]); pSrvList->AddrCount = 1; pSrvList->AddrArray[0] = inet_addr(DnsServIp); //DNS server IP address break; } default: Usage(argv[0]); break; } } else Usage(argv[0]); } } else Usage(argv[0]); // Calling function DnsQuery to query Host or PTR records status = DnsQuery(pOwnerName, //Pointer to OwnerName. wType, //Type of the record to be queried. DNS_QUERY_BYPASS_CACHE, // Bypasses the resolver cache on the lookup. pSrvList, //Contains DNS server IP address. &pDnsRecord, //Resource record that contains the response. NULL); //Reserved for future use. if (status) { if (wType == DNS_TYPE_A) printf("Failed to query the host record for %s and the error is %d \n", pOwnerName, status); else printf("Failed to query the PTR record and the error is %d \n", status); } else { if (wType == DNS_TYPE_A) { //convert the Internet network address into a string //in Internet standard dotted format. ipaddr.S_un.S_addr = (pDnsRecord->Data.A.IpAddress); printf("The IP address of the host %s is %s \n", pOwnerName, inet_ntoa(ipaddr)); // Free memory allocated for DNS records. DnsRecordListFree(pDnsRecord, freetype); } else { printf("The host name is %s \n", (pDnsRecord->Data.PTR.pNameHost)); // Free memory allocated for DNS records. DnsRecordListFree(pDnsRecord, freetype); } } LocalFree(pSrvList); }
按一下 [專案] 功能表上的 [屬性]。
在 [項目屬性] 對話框中,展開 [組態屬性] 底下的 [鏈接器],按兩下 [命令行],然後將下列連結庫新增至 [其他選項] 方塊:
- Ws2_32.lib
- Dnsapi.lib
按 Ctrl+Shift+B 建置方案。
測試範例
尋找對應至主機名稱的 IP 位址:
Q831226.exe -n <hostname> -t A -s <IP address of DNS server>
注意
hostname 是正在查詢之計算機名稱的佔位元。
尋找對應至 IP 位址的主機名稱:
Q831226.exe -n <xxx.xxx.xxx.xxx> -t PTR -s <IP address of DNS server>
注意
xxx.xxx.xxx.xxx 是正在查詢之計算機的IP位址占位元。
參考資料
如需 DNS 查閱的詳細資訊,請參閱: DnsQuery_A函式。