概述
DNS(Domain Name System,域名系统)是一种分布式数据库服务,用于将人们容易记忆的域名与计算机网络中用于寻址和定位的IP地址进行映射。在互联网上,每一台设备都有一个唯一的IP地址。但由于IP地址通常是一串难以记忆的数字,因此DNS系统应运而生,它提供了一种将人类可读的、具有一定逻辑结构的域名转换为IP地址的服务。
当用户在浏览器中输入一个网址时,实际上是触发了一个DNS解析过程,这个过程包括如下步骤。
查询本地DNS缓存:首先检查本机是否有该域名对应的IP地址记录。
递归查询:如果没有命中缓存,则请求发送到用户的ISP提供的本地DNS服务器,由本地DNS服务器负责发起递归查询流程,逐级向上询问根域名服务器、顶级域名服务器以及权威域名服务器,直到找到目标域名的IP地址。
响应并缓存:一旦权威域名服务器返回了域名对应的IP地址,这个信息会沿着查询路径返回给用户,并被沿途的DNS服务器缓存起来,以加快后续相同域名的查询速度。
CHP_DNS类
在C++中,获取DNS域名对应的IP地址通常不直接通过编写原始的DNS查询协议来实现(虽然理论上可以这样做),而是调用操作系统提供的网络库或API来进行解析。这是因为直接处理DNS协议细节相当复杂且容易出错,而操作系统和标准库已经封装好了这些功能。
gethostbyname函数和getaddrinfo函数用于获取域名对应的IP地址,但这两个函数都是阻塞的。在非阻塞的使用场景下,直接使用这两个函数不太合适。为了方便应用层使用,我们封装了异步DNS解析类CHP_DNS。CHP_DNS类是一个单实例类,从CHP_BaseThread类派生。CHP_DNS类的头文件,可参考下面的示例代码。
#pragma once#include <string>#include <map>#include "HP_BaseThread.h"#include "HP_Mutex.h"class CHP_DNS : public CHP_BaseThread{public: static void Open(); static CHP_DNS *&Singleton(); static void Close(); unsigned int FetchIP(const char *pszIP); void DefetchIP(const char *pszIP); static int GetIP(const char *pszIP, unsigned int &uiIP);protected: CHP_DNS(); virtual ~CHP_DNS(); virtual unsigned int Run();private: typedef struct _TDNSInfo { _TDNSInfo() { uiIP = 0; uiLastGotTick = 0; uiLastActiveTick = 0; } unsigned int uiIP; unsigned int uiLastGotTick; unsigned int uiLastActiveTick; }TDNSInfo; typedef std::map<std::string, TDNSInfo> IPToDNSInfoMap; static CHP_DNS *m_pThis; IPToDNSInfoMap m_mapIPToDNSInfo; bool m_bMapChanged; CHP_Mutex m_mutexMap;};
CHP_DNS类导出了两个实例成员函数和一个静态成员函数,下面分别进行介绍。
FetchIP:非阻塞获取DNS。参数pszIP为IP地址或域名;返回值为0时,表示没有解析成功,需要继续调用本函数,其他表示解析成功的IP地址。
DefetchIP:取消非阻塞获取DNS。当FetchIP一直返回0,上层判断超时后,最好调用本接口进行释放。否则,底层会一直尝试去解析,进而影响其他地址的解析过程。参数pszIP为IP地址或域名。
GetIP:阻塞获取DNS,静态函数。参数pszIP为IP地址或域名,参数uiIP为解析成功的IP地址,返回值为0表示成功,其他表示错误码。
总结
DNS解析是一种将域名(比如:www.example.com)转换为相应的IP地址(比如:192.168.1.100)的过程,这个过程是由DNS服务器完成的。DNS解析是互联网上的一个关键服务,它使得人们可以通过易记的域名来访问网站,而不需要记住复杂的IP地址。
总的来说,DNS解析是互联网上的一个关键服务,它使得人们可以通过易记的域名来访问网站,而不需要记住复杂的IP地址。同时,DNS解析也是分布式存储的,通过多个服务器之间的协作,实现了快速、准确的域名到IP地址的转换。