linwu-hi / code-interview

前端面试小册,包含Vue面试题,React面试题,JS面试题,HTTP面试题,工程化面试题,CSS面试题,算法面试题,大厂面试题,高频面试题
194 stars 23 forks source link

面试官:DNS协议 是什么?说说DNS 完整的查询过程? #144

Open linwu-hi opened 1 year ago

linwu-hi commented 1 year ago

面试官:DNS协议及完整的查询过程

一、DNS协议是什么?

DNS(Domain Name System),域名系统,是互联网中的一项服务,用于将域名(例如www.example.com)解析为对应的IP地址(例如192.0.2.1)。DNS相当于一个翻译官,负责将人类可读的域名翻译成计算机可理解的IP地址,从而实现网络通信。

在计算机网络中,数据通信的核心是IP地址,但是IP地址是一串数字,不方便人们记忆和使用。因此,DNS就像一个电话簿一样,通过域名来查找相应的IP地址,使得人们可以使用便于记忆的域名来访问网站,而不必记住复杂的IP地址。

二、域名结构

域名是一个具有层次结构的标识系统,由一系列以点分隔的名字组成。从右向左,域名的层级结构由低级到高级,例如:www.example.com,其中.com为顶级域名,example为二级域名,www为三级域名。

域名系统的结构如下图所示:

. (根域名)
|
|-- com (顶级域名)
|   |
|   |-- example (二级域名)
|       |
|       |-- www (三级域名)
|           |
|           |-- ... (更多子域名)
|
|-- net (顶级域名)
|   |
|   |-- ...
|
|-- org (顶级域名)
|   |
|   |-- ...
|
... (更多顶级域名)

三、DNS查询的方式

DNS查询的方式有两种:

1. 递归查询

递归查询是一种由客户端向DNS服务器发起的查询方式,客户端会一直迭代查询直至得到最终的查询结果。在递归查询中,如果目标DNS服务器不知道某个域名的IP地址,它会向其他DNS服务器发起请求,直到找到能够解析该域名的DNS服务器为止。

2. 迭代查询

迭代查询是一种DNS服务器之间的查询方式,DNS服务器之间会相互请求信息,但不会一直迭代查询直至得到最终结果。每个DNS服务器只会返回下一级的DNS服务器地址给客户端,让客户端继续查询。

四、域名缓存

DNS查询过程中,为了减少查询时间和减轻DNS服务器负担,会在客户端和DNS服务器上设置缓存。查询过的域名和对应的IP地址会被缓存一段时间,以便下次查询时可以直接使用缓存结果,加快查询速度。

客户端和DNS服务器的缓存分别为:

五、完整的DNS查询过程

下面是一个完整的DNS查询过程:

  1. 首先搜索浏览器的DNS缓存,如果存在目标域名的缓存结果,则直接返回IP地址,查询结束。

  2. 如果浏览器缓存中没有目标域名的结果,继续搜索操作系统的DNS缓存,如果存在目标域名的缓存结果,则直接返回IP地址,查询结束。

  3. 如果操作系统缓存中没有目标域名的结果,将域名发送给本地域名服务器。

  4. 本地域名服务器首先搜索自己的缓存,如果存在目标域名的缓存结果,则直接返回IP地址,查询结束。

  5. 如果本地域名服务器的缓存中没有目标域名的结果,本地域名服务器会按照递归查询的方式,向更高级的DNS服务器发起请求。

  6. 递归查询中,如果某个DNS服务器无法解析目标域名,则该DNS服务器会向更高级的DNS服务器请求解析结果,直至找到能够解析目标域名的DNS服务器。

  7. 最终,本地域名服务器得到目标域名对应的IP地址,并将IP地址返回给操作系统,并缓存该结果。

  8. 操作系统将IP地址返回给浏览器,并缓存该结果。

  9. 浏览器得到目标域名对应的IP地址,开始与服务器建立连接,进行后续的网络通信。

整个DNS查询过程涉及多个级别的DNS服务器的协作和查询,直至找到目标域名对应的IP地址。

六、DNS查询过程中的代码示例

const dns = require('dns');

function dnsLookup(domain) {
  return new Promise((resolve, reject) => {
    dns.lookup(domain, (err, address, family) => {
      if (err) {
        reject(err);
      } else {
        resolve(address);
      }
    });
  });
}

const domainName = 'www.example.com';
dnsLookup(domainName)
  .then(ipAddress => {
    console.log(`The IP address of ${domainName} is ${ipAddress}`);
  })
  .catch(error => {
    console.error(`DNS lookup failed: ${error.message}`);
  });

在这个示例中,我们定义了一个dns_lookup函数来进行DNS查询,传入域名作为参数,然后使用socket.gethostbyname()函数来获取域名对应的IP地址。如果查询失败,会捕获socket.gaierror异常,并返回相应的错误信息。

参考文献