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] 

  • 相关阅读:
    b_lc_数组中最大数对和的最小值(排序+思维 | 进阶:第k)
    b_lc_使用服务器处理任务(模拟 + 堆)
    b_lc_插入后的最大值(贪心+区分正负数)
    b_lc_蓄水(反向思维:枚举取水次数)
    万能JDBC工具类【DBUtil 】
    Eureka服务注册中心
    springboot dubbo+zookeeper
    Thymleaf引擎模板
    多环境切换 & JSR303数据校验
    yaml配置注入
  • 原文地址:https://www.cnblogs.com/snser/p/4101729.html
Copyright © 2011-2022 走看看