本文提供了一个 Win32 控制台应用程序示例,该示例演示如何使用 DnsQuery 函数解析主机名和主机 IP。
原始产品版本: Winsock
原始 KB 数: 831226
创建演示如何使用 DnsQuery 函数的示例 Win32 控制台应用程序
在 Winsock 中,使用 getaddrinfo 函数而不是 getaddrbyname 函数在应用程序中托管名称。 该 getaddrbyname 函数已替换为 getaddrinfo 用于处理 IPv4 和 IPv6 寻址的函数。
Winsock 直到 Windows Server 2003 才开始考虑宽字符,其中包含了 getaddrinfo 函数的新版本。 新版本名为 GetAddrInfo。 如果需要所有基于 NT 的操作系统的解决方案,请使用 DNS 客户端 DNSQuery 函数解析主机名。 该 DNSQuery 函数有一个广泛版本,适用于 Microsoft Windows 2000 及更高版本的操作系统。
使用以下步骤创建演示如何使用该 DnsQuery 函数的示例 Win32 控制台应用程序。 该 DnsQuery 函数将查询发送到 DNS 服务器,以将主机名解析为 IP 地址,反之亦然。
开始Microsoft Visual Studio .NET。
在“项目类型”下,单击“视觉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函数。