使用 DnsQuery 函式以 Visual C++ .NET 解析主機名稱和主機位址
本文提供 Win32 主控台應用程式範例,說明如何使用 DnsQuery
函式來解析主機名稱和主機 IP。
原始產品版本: Winsock
原始 KB 編號: 831226
建立範例 Win32 主控台應用程式,說明如何使用 DnsQuery 函式
在 Winsock 中 getaddrinfo
,使用 函式, getaddrbyname
而不是函式來裝載應用程式中的主機名稱。 函 getaddrbyname
式已由 getaddrinfo
處理 IPv4 和 IPv6 定址的函式取代。
Winsock 在 Windows Server 2003 中,直到最近包含新版 getaddrinfo
函式的 Windows Server 2003 中才算出寬字元。 新版本的名稱為 GetAddrInfo。 如果您需要所有 NT 型作業系統的解決方案,請使用 DNS 用戶端 DNSQuery 函式來解析主機名稱。 此 DNSQuery
函式具有應該在 Microsoft Windows 2000 和更新版本作業系統上運作的寬版本。
使用下列步驟來建立範例 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函式。