如何进行域名解析?如何清理DNS缓存?(附源码)

2024-04-27 12:44

本文主要是介绍如何进行域名解析?如何清理DNS缓存?(附源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1、什么是域名?

2、为什么使用域名?

3、域名解析的完整流程

4、调用gethostbyname系统接口将域名解析成IP地址

5、为什么需要清理系统DNS缓存?

6、使用cmd命令清理DNS缓存

7、通过代码去清除系统DNS缓存


C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.htmlVC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html       当我们使用域名访问远端的服务器时,需要先将域名转换成IP地址,然后通过IP地址去连接远端的服务器。这个将域名转换成IP地址的过程就叫做域名解析。操作系统中会将最近解析过的域名与IP地址缓存起来,称之为DNS缓存,有时可能需要清理DNS缓存,重新获取最新的IP地址。今天就给大家介绍一下如何进行域名解析及域名解析的完整流程,以及如何刷新DNS缓存,以供大家借鉴或参考。

1、什么是域名?

        域名是指互联网中的网站或者服务器的地址,这些名称由多个字符组成,通常是以“.com”、“.net”、“.cn”等结尾,比如大家常用的www.baidu.com(百度)、www.163.com(网易)等。一个好的域名,是连接客户和企业的桥梁,可以增加企业的知名度,使得客户更加容易地找到它们的网站,提高客户的转化率。

2、为什么使用域名?

       首先,域名便于记忆。由于IP地址不方便记忆且不能显示地址组织的名称和性质,人们设计出了域名,并通过域名系统(DNS,Domain Name System)来将域名和IP地址相互映射。域名好记忆很多,使人能更方便地访问互联网,而不用去记住能够被机器直接读取的IP地址数串。

       其次,远端服务器的IP可能会变动。域名一旦确定下来,一般就不会频繁地更改,特别是百度和网易这种门户网站,用户习惯使用固定的域名去访问指定的网站。但域名对应的IP地址可能会变更,在IP地址变更后,用户还能正常地通过域名去访问(对域名进行解析获取最新的IP地址)。

       此外,同一个域名可能会配置多个IP地址,不同的IP地址对应着不同的运营商线路,比如移动线路、电信线路和联通线路(不同的用户可能使用不同运营商的网络),从不同线路进来的,会解析出对应线路的IP地址,这样就避免了跨运营商网络访问,可以有效地提高访问的速度。

有的客户端软件支持用户去配置要访问的服务器地址,可以直接添加域名地址。有的软件则会内置要访问的服务器域名,不需要将服务器地址的配置暴露给用户(没有提供配置远端服务器地址的入口),软件在登录时直接使用内置的域名地址登录远端的服务器,比如QQ、微信及企业微信等。

3、域名解析的完整流程

       在进行域名解析时,底层会使用专用的DNS域名查询协议去查询域名对应IP地址。一般我们不需要关注DNS查询协议具体的格式和交互过程,我们只需要了解查询的大概流程即可。下面我们就来详细介绍一下域名解析的完整流程。

       DNS服务器大致分为三种类型:根DNS服务器、顶级域DNS服务器和权威DNS服务器,其中顶级域DNS服务器主要负责诸如com、org、net、edu、gov 等顶级域名,如下:

       根DNS服务器存储了所有顶级域DNS服务器的 IP 地址,可以通过根服务器找到顶级域服务器,比如百度的域名www.baidu.com,根服务器会返回所有维护 com 这个顶级域服务器的 IP 地址。然后你任选其中一个顶级域服务器发送请求,该顶级域服务器拿到域名后能够给出负责当前域的权威服务器地址。以百度的域名为例,顶级域服务器将返回所有负责百度这个域的权威服务器地址。接着任选其中一个权威服务器地址查询“www.baidu.com”的具体 IP 地址,最终权威服务器会返回给你具体的 IP 地址。此外,本地 DNS 服务器是具有缓存功能的,通常两天内的记录都会被缓存。

       所以,通过DNS系统查询域名对应的 IP 的具体步骤如下

  • ① 操作系统先查本地 hosts文件 中是否有记录,如果有,则直接返回相对应映射的IP地址。hosts文件位于C:\Windows\System32\drivers\etc路径中,内容如下:

  • ② 如果本地hosts文件中没有配置,则主机向自己的本地DNS服务器发送查询报文,如果本地DNS服务器缓存中有,将直接返回结果。
  • ③ 如果本地服务器缓存中没有(操作系统中会有DNS缓存),则从内置在内部的根DNS服务器列表(全球13台,固定的IP地址)中选一个发送查询报文。
  • ④ 根服务器解析域名中的后缀名,告诉本地服务器负责该后缀名的所有顶级服务器列表。
  • ⑤ 本地服务器选择其中一个顶级域服务器发送查询请求,顶级域服务器拿到域名后继续解析,返回对应域的所有权威服务器列表。
  • ⑥ 本地服务器再向返回的权威服务器发送查询报文,最终会从某一个权威服务器上得到具体的 IP 地址。
  • ⑦ 主机返回结果IP

        在这里,给大家重点推荐一下我的几个热门畅销专栏(博客主页还有其他专栏,可以去查看)

专栏1:(该精品技术专栏的订阅量已达到430多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!)

C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2: 

C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战经验为基础,总结并讲解一些的C/C++基础与进阶内容,以图文并茂的方式对C++相关知识点进行详细地展开与剖析!专栏涉及了C/C++开发领域多个方面的内容,同时给出C/C++及网络方面的常见笔试面试题,并详细讲述Visual Studio常用调试手段与技巧!

专栏3: 

VC++常用功能开发汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585

专栏将10多年C++开发实践中常用的功能,以高质量的代码展现出来,并对相关功能的实现细节进行了详细的说明。这些常用的代码,其质量与稳定性是有保证的,可以直接拿过去使用,可以有效地解决C++软件开发过程中遇到的问题。


4、调用gethostbyname系统接口将域名解析成IP地址

       当我们使用客户端软件或者浏览器通过域名访问远端的服务器时,作为用户是不感知域名解析的过程的,如果当前使用的是浏览器,则由浏览器去负责进行域名解析;如果当前使用的是客户端软件,则由客户端软件通过代码去完成域名解析。

       那如何通过代码将域名解析成IP地址呢?其实很简单,只要调用系统API函数gethostbyname即可实现。

注意,gethostbyname函数可能会产生短暂的堵塞,该函数内部会先到系统DNS缓存中去查找;如果没找到,则到网卡上配置的DNS服务器上去查询域名对应的IP地址;如果本地DNS查询不到,则会到远端的DNS服务器上去查询,所以这个域名解析的过程可能会比较耗时。至于DNS域名的详细查询过程,文章开始时已经详细讲述,此处就不再赘述了。

       所以,我们需要将对gethostbyname函数调用的代码,放置在一个新的线程中,等解析出来后再将IP信息投递出来给主线程。相关的代码如下所示:

// 域名解析线程函数
UINT __stdcall QueryDomainThread( LPVOID pParam )
{char* lpszDomainName = (char*)pParam; struct hostent *pHost = gethostbyname( lpszDomainName ); if( NULL == pHost )  {   // ::PostMessage // 通知主线程域名解析失败return 0;   }if ( pHost->h_addr_list[0] != NULL ) { u32 dwIP = (*(in_addr*)pHost->h_addr_list[0]).S_un.S_addr; // ::PostMessage // 通知主线程域名解析成功,将解析出来的IP投递过去}  return 0; 
}// 发起域名解析,创建新的线程去解析
LRESULT StartQueryDomain( char* lpszDomainName )
{// 此处不能直接将局部变量lpszDomainName传到线程函数中,因为启动线程的_beginthreadex返回时,线程函数不一定跑起来了// 所以最好搞一个成员变量或者全局变量,将lpszDomainName中的字符串拷贝下来,然后给_beginthreadex传递这个声明周期// 更长的变量strcpy( g_szMDomainName, lpszDomainName );// 线程函数QueryDomainThread的实现,上面已经给出HANDLE hThread= (HANDLE)_beginthreadex( NULL, 0, QueryDomainThread, (void*)g_szMDomainName, 0, NULL );if( hThread != NULL ){CloseHandle( hThread );return S_OK;}return S_FALSE;
}

5、为什么需要清理系统DNS缓存?

       假设服务器的IP地址变更,但我们PC端的系统DNS缓存中没有更新(我们在实际项目中遇到过),根据上面讲到的域名解析的流程,我们PC客户端软件使用域名访问远端的服务器时,发现本端系统DNS缓存中存放有域名对应的IP地址,就会直接从缓存中取出IP地址,就不会再向DNS服务器请求IP地址了。

系统之所以要建立系统DNS缓存,目的是为了提高应用访问服务器的效率,进行域名解析时如果系统缓存中目标域名对应的IP记录,直接取出来使用即可,就不用每次都向域名服务器发起域名查询请求,有效地减少了域名解析的时间。但DNS缓存也有不好的影响,比如此处的问题。

但从系统DNS缓存中取出的是老的IP地址,服务器IP地址已经变更,所以也就无法访问到服务器了。

       当遇到这类可以连外网但服务器无法访问时,可能是系统DNS缓存引起的,可以尝试清理一下系统DNS缓存,这样在解析域名时就会向DNS服务器发起域名查询请求,就能查询到最新的IP地址了,也就能正常地访问到服务器了。

6、使用cmd命令清理DNS缓存

       可以直接在cmd命令行窗口中使用ipconfig /flushdns命令即可清理系统的DNS缓存,如下所示:

这个命令其实是调用系统程序ipconfig.exe,在程序启动时给程序传递命令行参数/flushdns,程序启动起来后检测到命令行参数/flushdns,就会去执行清理DNS缓存的操作。

       我们还可以使用ipconfig /displaydns命令去查看系统DNS缓存中的信息,如下所示:

DNS缓存中存放着一条一条域名解析记录,每一条记录中的字段说明如下:

1)记录名称:是您查询 DNS 的名称,并且记录(地址或其他内容)属于该名称。
2)记录类型:是显示为数字的类型 - 尽管更常见的是通过名称来引用它们,但在内部(在 DNS 协议中)每个都有一个数字。类型 1 是“A”,表示“地址”,即 IPv4 地址。(IPv6 使用类型 28,“AAAA”,作为地址的四倍。)“PTR”,类型 12,是指向主机名的“指针”——最常用于将 IP 地址映射回其名称。“CNAME”是“规范名称”。
3)生存时间:是缓存条目必须到期的时间(以秒为单位)。
4)数据长度:似乎是以字节为单位的长度 - IPv4 地址为四个字节,IPv6 为十六个字节。对于 CNAME 或 PTR,Windows 显示一个静态数字(4 或 8,取决于您的系统)——这实际上是保存实际文本的内存地址的大小。
DNS 回复的“答案”部分是查询的实际答案,“附加”部分包含查找实际答案可能需要的信息。例如,粘合记录。
5)<type>记录:显示存储的实际值。

7、通过代码去清除系统DNS缓存

       上面我们说了,在cmd中执行系统DNS缓存清理的命令其实就是给系统程序ipconfig.exe传递了/flushdns参数,ipconfig.exe程序内部应该是调用系统库中的接口去实现清理的。于是在系统目录中找到ipconfig.exe文件,然后拖入到Dependency Walker工具中,看看ipconfig.exe有没有引用系统DNS相关的库以及调用了哪个具体的接口

       拖入后看到ipconfig.exe引用了系统库DNSAPI.dll,并看到调用了该库中的DnsFlushResolverCache接口:

于是到微软MSDN上搜索DnsFlushResolverCache函数,但并没有搜索到,那基本可以确定该接口是没有公开的。

       对于这类非公开的API函数,那可以使用LoadLibrary显示加载,并用GetProcess得到函数指针,直接调用之即可通过搜索,得到该函数的原型声明:

BOOL  WINAPI  DnsFlushResolverCache(VOID);

所以,从DNSAPI.DLL动态库中显式加载调用DnsFlushResolverCache的代码如下所示:

BOOL __stdcall DnsFlushResolverCache()
{BOOL bRet = FALSE;typedef BOOL (WINAPI *PfuncDnsFlushResolverCache)(VOID);HMODULE hDnsModule = LoadLibrary( _T("dnsapi.dll") );if ( hDnsModule != NULL ) {PfuncDnsFlushResolverCache pFlushFun = GetProcAddress( hDnsModule, "DnsFlushResolverCache" );if ( pFlushFun != NULL ){pFlushFun();bRet = TRUE;}FreeLibrary( hDnsModule );}return bRet;
}

这样我们在软件登录服务器失败时,可以尝试自动清理一下缓存,然后重新发起登录。

这篇关于如何进行域名解析?如何清理DNS缓存?(附源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940534

相关文章

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

Python使用date模块进行日期处理的终极指南

《Python使用date模块进行日期处理的终极指南》在处理与时间相关的数据时,Python的date模块是开发者最趁手的工具之一,本文将用通俗的语言,结合真实案例,带您掌握date模块的六大核心功能... 目录引言一、date模块的核心功能1.1 日期表示1.2 日期计算1.3 日期比较二、六大常用方法详

Python使用DrissionPage中ChromiumPage进行自动化网页操作

《Python使用DrissionPage中ChromiumPage进行自动化网页操作》DrissionPage作为一款轻量级且功能强大的浏览器自动化库,为开发者提供了丰富的功能支持,本文将使用Dri... 目录前言一、ChromiumPage基础操作1.初始化Drission 和 ChromiumPage

CentOS 7部署主域名服务器 DNS的方法

《CentOS7部署主域名服务器DNS的方法》文章详细介绍了在CentOS7上部署主域名服务器DNS的步骤,包括安装BIND服务、配置DNS服务、添加域名区域、创建区域文件、配置反向解析、检查配置... 目录1. 安装 BIND 服务和工具2.  配置 BIND 服务3 . 添加你的域名区域配置4.创建区域

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

Linux修改pip和conda缓存路径的几种方法

《Linux修改pip和conda缓存路径的几种方法》在Python生态中,pip和conda是两种常见的软件包管理工具,它们在安装、更新和卸载软件包时都会使用缓存来提高效率,适当地修改它们的缓存路径... 目录一、pip 和 conda 的缓存机制1. pip 的缓存机制默认缓存路径2. conda 的缓

Redis解决缓存击穿问题的两种方法

《Redis解决缓存击穿问题的两种方法》缓存击穿问题也叫热点Key问题,就是⼀个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击,本文给大家介绍了Re... 目录引言解决办法互斥锁(强一致,性能差)逻辑过期(高可用,性能优)设计逻辑过期时间引言缓存击穿:给

Jackson库进行JSON 序列化时遇到了无限递归(Infinite Recursion)的问题及解决方案

《Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursion)的问题及解决方案》使用Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursi... 目录解决方案‌1. 使用 @jsonIgnore 忽略一个方向的引用2. 使用 @JsonManagedR