zoukankan      html  css  js  c++  java
  • C++实现DNS域名解析

    一、概述

    现在来搞定DNS域名解析,其实这是前面一篇文章C++实现Ping里面的遗留问题,要干的活是ping的过程中画红线的部分:

    cmd下域名解析的命令是nslookup,比如“nslookup www.baidu.com”的结果如下:

    其中,Address返回的就是www.baidu.com对应的IP地址,这个可能有多个

    Alias指别名,也就是说www.baidu.com是www.a.shifen.com的别名,而www.a.shifen.com则是www.baidu.com的规范名(Canonical Name,CName),具体参考RFC1035 3.2.2 & wikipedia

     [转载请保留本文地址:http://www.cnblogs.com/goagent/p/4101729.html] 

    二、实现结果预览

    先看一下最终搞成了什么样子

    输入:域名字符串

    输出:IP列表、CName列表、DNS查询所用时间

     

    [转载请保留本文地址:http://www.cnblogs.com/goagent/p/4101729.html] 

    三、相关技术

    3.1、UDP or TCP ? (RFC1035 4.2)

    UDP:DNS查询和回复采用低开销高性能的UDP,端口号为53。

    TCP:辅助DNS服务器从主DNS服务器拉取最新数据时,采用可靠的TCP传输,端口号也为53。

    我们这里做DNS查询采用UDP,53端口。

    3.2、DNS查询/回复包头部解析 (RFC1035 4.1.1)

    重点介绍一下我们关心的部分:

    ID(16bits):标识符,一般填入本进程的标识符

    QR(1bits):标志位,查询包为0,回复包为1

    Opcode(4bits):查询的种类,标准查询为0

    QDCOUNT(16bits):DNS查询/回复包数据部分Question字段的个数

    ANCOUNT(16bits):DNS查询/回复包数据部分Answer字段的个数

    3.2、DNS查询/回复包数据部分解析 (RFC1035 4.1.2 & 4.1.3)

    查询/回复包的数据部分依次为QDCOUNT个Question字段、ANCOUNT个Answer字段....

    对于任意字段,其格式如下:

    Name(不定长):域名,这部分的格式比较复杂,后面单独说。

    TYPE(16bits):查询类型/回复包RDATA类型,比如TYPE=1表示主机IP地址、TYPE=5表示CNAME,详见RFC1035 3.2.2

    CLASS(16bits):类,一般情况下CLASS=1表示Internet,详见RFC1035 3.2.4

    TTL(32bits,仅回复包):生存时间

    RDLENGTH(16bits,仅回复包):RDATA部分的字节数

    RDATA(不定长,仅回复包):资源数据,具体格式取决于TYPE和CLASS,比如TYPE=1、CLASS=1时,RDATA为四个字节的IP地址

    3.3、Name解析&消息压缩

    3.3.1、一般格式 (RFC1035 4.1.2)

    标签内容长度(1个字节) + 标签内容,以标签内容长度0作为Name的结束符,例如:

    3.3.2、消息压缩格式 (RFC1035 4.1.4)

    如果标签内容长度的二进制前两位是11,则表示消息压缩。

    此时,标签内容长度1个字节+后面的1个字节一共16位,后14位表示相对DNS包起始地址的偏移(Byte),例如:

    上述例子中,DNS包起始地址为0x0000,c0 13的二进制为11000000 00010003,即跳转偏移为0x13个字节,对应的数据为03 63 6f 6d 00。

    RFC1035中规定,支持的消息压缩规则为:

    ①以内容长度0结尾的标签序列

    ②偏移指针

    ③标签序列+偏移指针

    也就是说,Name的消息压缩要求偏移指针必须在Name的尾部,且不支持同一级存在多个偏移指针(偏移指针序列),

    但Name的消息压缩支持嵌套的偏移指针,即指针指向的偏移位置仍然是以偏移指针结尾的数据

     [转载请保留本文地址:http://www.cnblogs.com/goagent/p/4101729.html] 

    四、代码实现

     1 #pragma once
     2 
     3 //这里需要导入库 Ws2_32.lib,在不同的IDE下可能不太一样
     4 //#pragma comment(lib, "Ws2_32.lib")
     5 
     6 #include <windows.h>
     7 #include <string>
     8 #include <vector>
     9 
    10 #define MAX_DOMAINNAME_LEN  255
    11 #define DNS_PORT            53
    12 #define DNS_TYPE_SIZE       2
    13 #define DNS_CLASS_SIZE      2
    14 #define DNS_TTL_SIZE        4
    15 #define DNS_DATALEN_SIZE    2
    16 #define DNS_TYPE_A          0x0001 //1 a host address
    17 #define DNS_TYPE_CNAME      0x0005 //5 the canonical name for an alias
    18 #define DNS_PACKET_MAX_SIZE (sizeof(DNSHeader) + MAX_DOMAINNAME_LEN + DNS_TYPE_SIZE + DNS_CLASS_SIZE)
    19 
    20 struct DNSHeader
    21 {
    22     USHORT usTransID; //标识符
    23     USHORT usFlags; //各种标志位
    24     USHORT usQuestionCount; //Question字段个数 
    25     USHORT usAnswerCount; //Answer字段个数
    26     USHORT usAuthorityCount; //Authority字段个数
    27     USHORT usAdditionalCount; //Additional字段个数
    28 };
    29 
    30 class CDNSLookup
    31 {
    32 public:
    33     CDNSLookup();
    34     ~CDNSLookup();
    35 
    36     BOOL DNSLookup(ULONG ulDNSServerIP, char *szDomainName, std::vector<ULONG> *pveculIPList = NULL, std::vector<std::string> *pvecstrCNameList = NULL, ULONG ulTimeout = 1000, ULONG *pulTimeSpent = NULL);
    37     BOOL DNSLookup(ULONG ulDNSServerIP, char *szDomainName, std::vector<std::string> *pvecstrIPList = NULL, std::vector<std::string> *pvecstrCNameList = NULL, ULONG ulTimeout = 1000, ULONG *pulTimeSpent = NULL);
    38 
    39 private:
    40     BOOL Init();
    41     BOOL UnInit();
    42     BOOL DNSLookupCore(ULONG ulDNSServerIP, char *szDomainName, std::vector<ULONG> *pveculIPList, std::vector<std::string> *pvecstrCNameList, ULONG ulTimeout, ULONG *pulTimeSpent);
    43     BOOL SendDNSRequest(sockaddr_in sockAddrDNSServer, char *szDomainName);
    44     BOOL RecvDNSResponse(sockaddr_in sockAddrDNSServer, ULONG ulTimeout, std::vector<ULONG> *pveculIPList, std::vector<std::string> *pvecstrCNameList, ULONG *pulTimeSpent);
    45     BOOL EncodeDotStr(char *szDotStr, char *szEncodedStr, USHORT nEncodedStrSize);
    46     BOOL DecodeDotStr(char *szEncodedStr, USHORT *pusEncodedStrLen, char *szDotStr, USHORT nDotStrSize, char *szPacketStartPos = NULL);
    47     ULONG GetTickCountCalibrate();
    48 
    49 private:
    50     BOOL m_bIsInitOK;
    51     SOCKET m_sock;
    52     WSAEVENT m_event;
    53     USHORT m_usCurrentProcID;
    54     char *m_szDNSPacket;
    55 };
    View Code [DNSLookup.h]
      1 #include "DNSLookup.h"
      2 #include <stdio.h>
      3 #include <string.h>
      4 
      5 CDNSLookup::CDNSLookup() : 
      6     m_bIsInitOK(FALSE), 
      7     m_sock(INVALID_SOCKET),
      8     m_szDNSPacket(NULL)
      9 {
     10     m_bIsInitOK = Init();
     11 }
     12 
     13 CDNSLookup::~CDNSLookup()
     14 {
     15     UnInit();
     16 }
     17 
     18 BOOL CDNSLookup::DNSLookup(ULONG ulDNSServerIP, char *szDomainName, std::vector<ULONG> *pveculIPList, std::vector<std::string> *pvecstrCNameList, ULONG ulTimeout, ULONG *pulTimeSpent)
     19 {
     20     return DNSLookupCore(ulDNSServerIP, szDomainName, pveculIPList, pvecstrCNameList, ulTimeout, pulTimeSpent);
     21 }
     22 
     23 BOOL CDNSLookup::DNSLookup(ULONG ulDNSServerIP, char *szDomainName, std::vector<std::string> *pvecstrIPList, std::vector<std::string> *pvecstrCNameList, ULONG ulTimeout, ULONG *pulTimeSpent)
     24 {
     25     std::vector<ULONG> *pveculIPList = NULL;
     26     if (pvecstrIPList != NULL)
     27     {
     28         std::vector<ULONG> veculIPList;
     29         pveculIPList = &veculIPList;
     30     }
     31 
     32     BOOL bRet = DNSLookupCore(ulDNSServerIP, szDomainName, pveculIPList, pvecstrCNameList, ulTimeout, pulTimeSpent);
     33 
     34     if (bRet)
     35     {
     36         pvecstrIPList->clear();
     37         char szIP[16] = {''};
     38         for (std::vector<ULONG>::iterator iter = pveculIPList->begin(); iter != pveculIPList->end(); ++iter)
     39         {
     40             BYTE *pbyIPSegment = (BYTE*)(&(*iter));
     41             //sprintf_s(szIP, 16, "%d.%d.%d.%d", pbyIPSegment[0], pbyIPSegment[1], pbyIPSegment[2], pbyIPSegment[3]);
     42             sprintf(szIP, "%d.%d.%d.%d", pbyIPSegment[0], pbyIPSegment[1], pbyIPSegment[2], pbyIPSegment[3]);
     43             pvecstrIPList->push_back(szIP);
     44         }
     45     }
     46 
     47     return bRet;
     48 }
     49 
     50 
     51 BOOL CDNSLookup::Init()
     52 {
     53     WSADATA wsaData;
     54     if (WSAStartup(MAKEWORD(2, 2), &wsaData) == SOCKET_ERROR)
     55     {
     56         return FALSE;
     57     }
     58     
     59     if ((m_sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
     60     {
     61         return FALSE;
     62     }
     63 
     64     m_event = WSACreateEvent();
     65     WSAEventSelect(m_sock, m_event, FD_READ);
     66 
     67     m_szDNSPacket = new (std::nothrow) char[DNS_PACKET_MAX_SIZE];
     68     if (m_szDNSPacket == NULL)
     69     {
     70         return FALSE;
     71     }
     72 
     73     m_usCurrentProcID = (USHORT)GetCurrentProcessId();
     74 
     75     return TRUE;
     76 }
     77 
     78 BOOL CDNSLookup::UnInit()
     79 {
     80     WSACleanup();
     81 
     82     if (m_szDNSPacket != NULL)
     83     {
     84         delete [] m_szDNSPacket;
     85     }
     86 
     87     return TRUE;
     88 }
     89 
     90 BOOL CDNSLookup::DNSLookupCore(ULONG ulDNSServerIP, char *szDomainName, std::vector<ULONG> *pveculIPList, std::vector<std::string> *pvecstrCNameList, ULONG ulTimeout, ULONG *pulTimeSpent)
     91 {
     92     if (m_bIsInitOK == FALSE || szDomainName == NULL)
     93     {
     94         return FALSE;
     95     }
     96 
     97     //配置SOCKET
     98     sockaddr_in sockAddrDNSServer; 
     99     sockAddrDNSServer.sin_family = AF_INET; 
    100     sockAddrDNSServer.sin_addr.s_addr = ulDNSServerIP;
    101     sockAddrDNSServer.sin_port = htons( DNS_PORT );
    102 
    103     //DNS查询与解析
    104     if (!SendDNSRequest(sockAddrDNSServer, szDomainName)
    105         || !RecvDNSResponse(sockAddrDNSServer, ulTimeout, pveculIPList, pvecstrCNameList, pulTimeSpent))
    106     {
    107         return FALSE;
    108     }
    109 
    110     return TRUE;
    111 }
    112 
    113 BOOL CDNSLookup::SendDNSRequest(sockaddr_in sockAddrDNSServer, char *szDomainName)
    114 {
    115     char *pWriteDNSPacket = m_szDNSPacket;
    116     memset(pWriteDNSPacket, 0, DNS_PACKET_MAX_SIZE);    
    117 
    118     //填充DNS查询报文头部
    119     DNSHeader *pDNSHeader = (DNSHeader*)pWriteDNSPacket;
    120     pDNSHeader->usTransID = m_usCurrentProcID;
    121     pDNSHeader->usFlags = htons(0x0100);
    122     pDNSHeader->usQuestionCount = htons(0x0001);
    123     pDNSHeader->usAnswerCount = 0x0000;
    124     pDNSHeader->usAuthorityCount = 0x0000;
    125     pDNSHeader->usAdditionalCount = 0x0000;
    126 
    127     //设置DNS查询报文内容
    128     USHORT usQType = htons(0x0001);
    129     USHORT usQClass = htons(0x0001);
    130     USHORT nDomainNameLen = strlen(szDomainName);
    131     char *szEncodedDomainName = (char *)malloc(nDomainNameLen + 2);
    132     if (szEncodedDomainName == NULL)
    133     {
    134         return FALSE;
    135     }
    136     if (!EncodeDotStr(szDomainName, szEncodedDomainName, nDomainNameLen + 2))
    137     {
    138         return FALSE;
    139     }
    140 
    141     //填充DNS查询报文内容
    142     USHORT nEncodedDomainNameLen = strlen(szEncodedDomainName) + 1;
    143     memcpy(pWriteDNSPacket += sizeof(DNSHeader), szEncodedDomainName, nEncodedDomainNameLen);
    144     memcpy(pWriteDNSPacket += nEncodedDomainNameLen, (char*)(&usQType), DNS_TYPE_SIZE);
    145     memcpy(pWriteDNSPacket += DNS_TYPE_SIZE, (char*)(&usQClass), DNS_CLASS_SIZE);
    146     free (szEncodedDomainName);
    147 
    148     //发送DNS查询报文
    149     USHORT nDNSPacketSize = sizeof(DNSHeader) + nEncodedDomainNameLen + DNS_TYPE_SIZE + DNS_CLASS_SIZE;
    150     if (sendto(m_sock, m_szDNSPacket, nDNSPacketSize, 0, (sockaddr*)&sockAddrDNSServer, sizeof(sockAddrDNSServer)) == SOCKET_ERROR)
    151     {
    152         return FALSE;
    153     }
    154 
    155     return TRUE;
    156 }
    157 
    158 BOOL CDNSLookup::RecvDNSResponse(sockaddr_in sockAddrDNSServer, ULONG ulTimeout, std::vector<ULONG> *pveculIPList, std::vector<std::string> *pvecstrCNameList, ULONG *pulTimeSpent)
    159 {
    160     ULONG ulSendTimestamp = GetTickCountCalibrate();
    161 
    162     if (pveculIPList != NULL)
    163     {
    164         pveculIPList->clear();
    165     }
    166     if (pvecstrCNameList != NULL)
    167     {
    168         pvecstrCNameList->clear();
    169     }
    170 
    171     char recvbuf[1024] = {''};
    172     char szDotName[128] = {''};
    173     USHORT nEncodedNameLen = 0;
    174 
    175     while (TRUE)
    176     {
    177         if (WSAWaitForMultipleEvents(1, &m_event, FALSE, 100, FALSE) != WSA_WAIT_TIMEOUT)
    178         {
    179             WSANETWORKEVENTS netEvent;
    180             WSAEnumNetworkEvents(m_sock, m_event, &netEvent);
    181 
    182             if (netEvent.lNetworkEvents & FD_READ)
    183             {
    184                 ULONG ulRecvTimestamp = GetTickCountCalibrate();
    185                 int nSockaddrDestSize = sizeof(sockAddrDNSServer);
    186 
    187                 //接收响应报文
    188                 if (recvfrom(m_sock, recvbuf, 1024, 0, (struct sockaddr*)&sockAddrDNSServer, &nSockaddrDestSize) != SOCKET_ERROR)
    189                 {
    190                     DNSHeader *pDNSHeader = (DNSHeader*)recvbuf;
    191                     USHORT usQuestionCount = 0;
    192                     USHORT usAnswerCount = 0;
    193 
    194                     if (pDNSHeader->usTransID == m_usCurrentProcID
    195                         && (ntohs(pDNSHeader->usFlags) & 0xfb7f) == 0x8100 //RFC1035 4.1.1(Header section format)
    196                         && (usQuestionCount = ntohs(pDNSHeader->usQuestionCount)) >= 0
    197                         && (usAnswerCount = ntohs(pDNSHeader->usAnswerCount)) > 0)
    198                     {
    199                         char *pDNSData = recvbuf + sizeof(DNSHeader);
    200 
    201                         //解析Question字段
    202                         for (int q = 0; q != usQuestionCount; ++q)
    203                         {
    204                             if (!DecodeDotStr(pDNSData, &nEncodedNameLen, szDotName, sizeof(szDotName)))
    205                             {
    206                                 return FALSE;
    207                             }
    208                             pDNSData += (nEncodedNameLen + DNS_TYPE_SIZE + DNS_CLASS_SIZE);
    209                         }
    210 
    211                         //解析Answer字段
    212                         for (int a = 0; a != usAnswerCount; ++a)
    213                         {
    214                             if (!DecodeDotStr(pDNSData, &nEncodedNameLen, szDotName, sizeof(szDotName), recvbuf))
    215                             {
    216                                 return FALSE;
    217                             }
    218                             pDNSData += nEncodedNameLen;
    219 
    220                             USHORT usAnswerType = ntohs(*(USHORT*)(pDNSData));
    221                             USHORT usAnswerClass = ntohs(*(USHORT*)(pDNSData + DNS_TYPE_SIZE));
    222                             ULONG usAnswerTTL = ntohl(*(ULONG*)(pDNSData + DNS_TYPE_SIZE + DNS_CLASS_SIZE));
    223                             USHORT usAnswerDataLen = ntohs(*(USHORT*)(pDNSData + DNS_TYPE_SIZE + DNS_CLASS_SIZE + DNS_TTL_SIZE));
    224                             pDNSData += (DNS_TYPE_SIZE + DNS_CLASS_SIZE + DNS_TTL_SIZE + DNS_DATALEN_SIZE);
    225 
    226                             if (usAnswerType == DNS_TYPE_A && pveculIPList != NULL)
    227                             {
    228                                 ULONG ulIP = *(ULONG*)(pDNSData);
    229                                 pveculIPList->push_back(ulIP);
    230                             }
    231                             else if (usAnswerType == DNS_TYPE_CNAME && pvecstrCNameList != NULL)
    232                             {
    233                                 if (!DecodeDotStr(pDNSData, &nEncodedNameLen, szDotName, sizeof(szDotName), recvbuf))
    234                                 {
    235                                     return FALSE;
    236                                 }
    237                                 pvecstrCNameList->push_back(szDotName);
    238                             }
    239 
    240                             pDNSData += (usAnswerDataLen);
    241                         }
    242 
    243                         //计算DNS查询所用时间
    244                         if (pulTimeSpent != NULL)
    245                         {
    246                             *pulTimeSpent = ulRecvTimestamp - ulSendTimestamp;
    247                         }
    248 
    249                         break;
    250                     }
    251                 }
    252             }
    253         }
    254 
    255         //超时退出
    256         if (GetTickCountCalibrate() - ulSendTimestamp > ulTimeout)
    257         {
    258             *pulTimeSpent = ulTimeout + 1;
    259             return FALSE;
    260         }
    261     }
    262 
    263     return TRUE;
    264 }
    265 
    266 /*
    267  * convert "www.baidu.com" to "x03wwwx05baidux03com"
    268  * 0x0000 03 77 77 77 05 62 61 69 64 75 03 63 6f 6d 00 ff
    269  */
    270 BOOL CDNSLookup::EncodeDotStr(char *szDotStr, char *szEncodedStr, USHORT nEncodedStrSize)
    271 {
    272     USHORT nDotStrLen = strlen(szDotStr);
    273 
    274     if (szDotStr == NULL || szEncodedStr == NULL || nEncodedStrSize < nDotStrLen + 2)
    275     {
    276         return FALSE;
    277     }
    278 
    279     char *szDotStrCopy = new char[nDotStrLen + 1];
    280     //strcpy_s(szDotStrCopy, nDotStrLen + 1, szDotStr);
    281     strcpy(szDotStrCopy, szDotStr);
    282 
    283     char *pNextToken = NULL;
    284     //char *pLabel = strtok_s(szDotStrCopy, ".", &pNextToken);
    285     char *pLabel = strtok(szDotStrCopy, ".");
    286     USHORT nLabelLen = 0;
    287     USHORT nEncodedStrLen = 0;
    288     while (pLabel != NULL)
    289     {
    290         if ((nLabelLen = strlen(pLabel)) != 0)
    291         {
    292             //sprintf_s(szEncodedStr + nEncodedStrLen, nEncodedStrSize - nEncodedStrLen, "%c%s", nLabelLen, pLabel);
    293             sprintf(szEncodedStr + nEncodedStrLen, "%c%s", nLabelLen, pLabel);
    294             nEncodedStrLen += (nLabelLen + 1);
    295         }
    296         //pLabel = strtok_s(NULL, ".", &pNextToken);
    297         pLabel = strtok(NULL, ".");
    298     }
    299 
    300     delete [] szDotStrCopy;
    301     
    302     return TRUE;
    303 }
    304 
    305 /*
    306  * convert "x03wwwx05baidux03comx00" to "www.baidu.com"
    307  * 0x0000 03 77 77 77 05 62 61 69 64 75 03 63 6f 6d 00 ff
    308  * convert "x03wwwx05baiduxc0x13" to "www.baidu.com"
    309  * 0x0000 03 77 77 77 05 62 61 69 64 75 c0 13 ff ff ff ff
    310  * 0x0010 ff ff ff 03 63 6f 6d 00 ff ff ff ff ff ff ff ff
    311  */
    312 BOOL CDNSLookup::DecodeDotStr(char *szEncodedStr, USHORT *pusEncodedStrLen, char *szDotStr, USHORT nDotStrSize, char *szPacketStartPos)
    313 {
    314     if (szEncodedStr == NULL || pusEncodedStrLen == NULL || szDotStr == NULL)
    315     {
    316         return FALSE;
    317     }
    318 
    319     char *pDecodePos = szEncodedStr;
    320     USHORT usPlainStrLen = 0;
    321     BYTE nLabelDataLen = 0;    
    322     *pusEncodedStrLen = 0;
    323 
    324     while ((nLabelDataLen = *pDecodePos) != 0x00)
    325     {
    326         if ((nLabelDataLen & 0xc0) == 0) //普通格式,LabelDataLen + Label
    327         {
    328             if (usPlainStrLen + nLabelDataLen + 1 > nDotStrSize)
    329             {
    330                 return FALSE;
    331             }
    332             memcpy(szDotStr + usPlainStrLen, pDecodePos + 1, nLabelDataLen);
    333             memcpy(szDotStr + usPlainStrLen + nLabelDataLen, ".", 1);
    334             pDecodePos += (nLabelDataLen + 1);
    335             usPlainStrLen += (nLabelDataLen + 1);
    336             *pusEncodedStrLen += (nLabelDataLen + 1);
    337         }
    338         else //消息压缩格式,11000000 00000000,两个字节,前2位为跳转标志,后14位为跳转的偏移
    339         {
    340             if (szPacketStartPos == NULL)
    341             {
    342                 return FALSE;
    343             }
    344             USHORT usJumpPos = ntohs(*(USHORT*)(pDecodePos)) & 0x3fff;
    345             USHORT nEncodeStrLen = 0;
    346             if (!DecodeDotStr(szPacketStartPos + usJumpPos, &nEncodeStrLen, szDotStr + usPlainStrLen, nDotStrSize - usPlainStrLen, szPacketStartPos))
    347             {
    348                 return FALSE;
    349             }
    350             else
    351             {
    352                 *pusEncodedStrLen += 2;
    353                 return TRUE;
    354             }
    355         }
    356     }
    357 
    358     szDotStr[usPlainStrLen - 1] = '';
    359     *pusEncodedStrLen += 1;
    360 
    361     return TRUE;
    362 }
    363 
    364 ULONG CDNSLookup::GetTickCountCalibrate()
    365 {
    366     static ULONG s_ulFirstCallTick = 0;
    367     static LONGLONG s_ullFirstCallTickMS = 0;
    368 
    369     SYSTEMTIME systemtime;
    370     FILETIME filetime;
    371     GetLocalTime(&systemtime);    
    372     SystemTimeToFileTime(&systemtime, &filetime);
    373     LARGE_INTEGER liCurrentTime;
    374     liCurrentTime.HighPart = filetime.dwHighDateTime;
    375     liCurrentTime.LowPart = filetime.dwLowDateTime;
    376     LONGLONG llCurrentTimeMS = liCurrentTime.QuadPart / 10000;
    377 
    378     if (s_ulFirstCallTick == 0)
    379     {
    380         s_ulFirstCallTick = GetTickCount();
    381     }
    382     if (s_ullFirstCallTickMS == 0)
    383     {
    384         s_ullFirstCallTickMS = llCurrentTimeMS;
    385     }
    386 
    387     return s_ulFirstCallTick + (ULONG)(llCurrentTimeMS - s_ullFirstCallTickMS);
    388 }
    View Code [DNSLookup.cpp]
     1 #include <stdio.h>
     2 #include <windows.h>
     3 #include "DNSLookup.h"
     4 
     5 int main(void)
     6 {
     7     char szDomainName[] = "www.baidu.com";
     8     std::vector<ULONG> veculIPList;
     9     std::vector<std::string> vecstrIPList;
    10     std::vector<std::string> vecCNameList;
    11     ULONG ulTimeSpent = 0;
    12     CDNSLookup dnslookup;
    13     BOOL bRet = dnslookup.DNSLookup(inet_addr("114.114.114.114"), szDomainName, &vecstrIPList, &vecCNameList, 1000, &ulTimeSpent);
    14 
    15     printf("DNSLookup result (%s):
    ", szDomainName);
    16     if (!bRet)
    17     {
    18         printf("timeout!
    ");
    19         return -1;
    20     }
    21 
    22     for (int i = 0; i != veculIPList.size(); ++i)
    23     {
    24         printf("IP%d(ULONG) = %u
    ", i + 1, veculIPList[i]);
    25     }
    26     for (int i = 0; i != vecstrIPList.size(); ++i)
    27     {
    28         printf("IP%d(string) = %s
    ", i + 1, vecstrIPList[i].c_str());
    29     }
    30     for (int i = 0; i != vecCNameList.size(); ++i)
    31     {
    32         printf("CName%d = %s
    ", i + 1, vecCNameList[i].c_str());
    33     }
    34     printf("time spent = %ums
    ", ulTimeSpent);
    35     
    36     return 0;
    37 }

     [转载请保留本文地址:http://www.cnblogs.com/goagent/p/4101729.html] 

  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/snser/p/4101729.html
Copyright © 2011-2022 走看看