美文网首页
Chromium是如何实现DNS的解析

Chromium是如何实现DNS的解析

作者: 咖啡不加盐0915 | 来源:发表于2017-09-28 10:26 被阅读0次

DNS解析是一种非常常见的解析方式,来看一下百度百科的说明:

DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协议运行在UDP协议之上,使用端口号53。在RFC文档中RFC 2181对DNS有规范说明,RFC 2136对DNS的动态更新进行说明,RFC 2308对DNS查询的反向缓存进行说明。

简单点说就是我们想登陆某一个网页,只需要记住有主观意义的域名,比如说www.bytedance.com, www.baidu.com, www.sina.cn 等等,甚至可以简单地把dns理解为一个key-value的分布式数据库,其中key值就是域名,而value就是域名对应的ip地址,这里并不是一一对应的关系,一个域名可以对应多个ip地址,这样做是为了防止当一个ip地址不可用时,可以切换到另一个ip地址,从而不会影响用户的业务。

关于dns的原理我们就简单介绍到这里,今天我们要讲的是chromium是如何实现dns解析的。大家可能对chromiun有点陌生,但我相信很多人一定都用过chrome浏览器,实际上chromiun就是chrome的项目源码名称,可不要小瞧chrome浏览器,其复杂程度不亚于一个操作系统,甚至你可以直接把chrome浏览器看成一个web操作系统,关于这个项目有很多值得学习的地方,比如说它的多进程调度,渲染器的使用,浏览器加速算法等等,在这里我们只关注它对于网络部分的实现.

Chromium中关于网络方面的实现均在net库中,实现了包括dns、http、udp、ftp、quic等等大家熟知的协议,大家感兴趣的话可以去网上下载chromium的源代码。

dns的代码路径是 src/net/dns, 通过下图可以看到文件有很多个,如果一个个点进去看,既浪费时间又很难真正理解dns的精髓。

下面我就带大家看一看chrome对于dns解析的实现:

第一步首先关注核心函数,这里的核心函数是指dns整个模块对外的一个接口,简单点说就是当用户在浏览器中输入网址时,主进程便会调用dns模块中的这个文件来获取相应的ip地址,而这里的核心函数就位于 host_resolver_impl.cc 中,其核心函数为:

int HostResolverImpl::Resolve(const RequestInfo& info,

RequestPriority priority,

AddressList* addresses,

const CompletionCallback& callback,

RequestHandle* out_req,

const BoundNetLog& source_net_log) ;

Key key = GetEffectiveKeyForRequest(info, source_net_log);

这里的key值时根据info得出的一组可以唯一标志dns中一种主机解析job,关于job的概念等会就会提到。

int rv = ResolveHelper(key, info, addresses, source_net_log);

可以看到在这里又新引入了一个ResolveHelper函数,这个函数的作用时根据计算得到的key值以及info值,依次判断是否为ip,能否从cache中得到,能否从host中得到,这个函数可以理解为一个辅助的解析函数。

JobMap::iterator jobit = jobs_.find(key);

Job* job;

加入辅助解析函数并未找到需要的ip地址,并且之前未启动相同的job(这里通过find函数来查找指定key值的job是否存在),则需要启动一个job来进行相应的dns解析,关于dns解析,这里有两种方式:

一种是要提到一个函数getaddrinfo(), 这个函数可以根据域名得到相应的ip地址,并且既可以用在ipv4上,也可以用在ipv6上,但由于其是一个系统级别的调用,因此是一个阻塞调用,chrome将这种方式称之为ProcTask方式:

而另外一种调用方式则是chromium按照dns协议规范,通过异步非阻塞的调用方式,实现了getaddrinfo()函数,这种方式被称之为DnsTask。

那究竟如何选择使用哪种方式来进行dns解析呢?还是要看代码,下面这些代码时job类中start()方法的实现:

void Start() override {

DCHECK_LE(num_occupied_job_slots_, 1u);

// Caution: Job::Start must not complete synchronously.

if (!system_only && had_dns_config_ &&

!ResemblesMulticastDNSName(key_.hostname)) {

StartDnsTask(); //满足上述条件后才使用DnsTask

} else {

StartProcTask(); //其余情况均使用ProcTask

}

}

当满足系统未指定解析方式、dns已经配置完成主机名满足一定条件才可以使用DnsTask,其余情况均使用ProcTask。

先来说一下ProcTask,这种方式较为简单,其最终回调用到函数SystemHostResolverCall() 中去, 而这个函数只是对 getaddrinfo() 做了一层封装而已,逻辑相对简单一些,感兴趣的同学可以去看一下源码,位置是在host_resolver.cc这个文件里。

DnsTask相对来说就复杂一些,简单点说就是通过调用StartA(),紧接着再调用

dns_query.cc、dns_transaction.cc,同时调用udp协议获取fd,然后将这个fd注册到网络库的io线程事件循环中,从而使得dns解析流程统一写到了异步回调的编程框架中。

好了,关于chromium中dns的解析暂时先说到这里,后续如果有更进一步的解析,我会及时更新并分享出来的。

相关文章

  • Chromium是如何实现DNS的解析

    DNS解析是一种非常常见的解析方式,来看一下百度百科的说明: DNS(Domain Name System,域名系...

  • DNS域名解析

    本文解决如果几个问题:1、什么是DNS域名解析2、域名解析过程3、如何搭建本地DNS服务器 什么是DNS域名解析 ...

  • 【Python与网络4】

    使用dnspython解析DNS dnspython模块介绍 dnspython是Python实现的一个DNS工具...

  • 撩课-Web大前端每天5道面试题-Day41

    1.DNS解析过程?若是新申请的域名如何查找DNS? 2.Ajax请求状态及意义? 3.使用JS实现获取文件扩展名...

  • 8-4 DNS

    DNS解析了解吗 DNS解析 查询方式 DNS劫持 DNS解析转发问题

  • 从url到页面展示的经过

    1.DNS解析 DNS解析过程充当了一个翻译的角色,实现了网址到IP地址的转换。 是一个递归查询的过程。所有网址真...

  • DNS解析

    DNS解析 了解DNS解析 域名到IP地址的映射,DNS解析请求 才有UDP数据报,且明文 DNS解析查询方式 D...

  • 22-域名系统DNS服务

    本章内容 ◆ 名字解析介绍◆ DNS服务工作原理◆ 实现主服务器◆ 实现反向解析区域◆ 实现从服务器◆ 实现子域◆...

  • DNS介绍以及模拟dns解析过程实验

    DNS简介DNS域名的解析过程DNS服务器的资源记录实验模拟DNS解析过程 DNS简介   DNS(Domain ...

  • Kubernetes Dns query调优

    Kubernetes 目前使用的kube-dns来实现集群内部的service dns记录解析。默认情况下/etc...

网友评论

      本文标题: Chromium是如何实现DNS的解析

      本文链接:https://www.haomeiwen.com/subject/bkjmextx.html