Android DNS机制

本文介绍了Android DNS的工作原理,包括DNS域名系统、Android DNS模块的入口函数getaddrinfo、查询方式顺序、DNS请求的目的地址管理以及DNS请求流程。重点阐述了Android设备在不同网络环境下的DNS查询策略,如4A和A请求,以及DNS服务器地址的保存顺序。同时,讨论了DNS请求的retry和timeout机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1,DNS

DNS全称Domain Name System(域名系统),顾名思义,就是把域名解析为指向的IP,让人们通过注册的域名可以方便的访问到网址的一种服务。域名解析就是域名到IP地址的转换过程。域名解析的工作由DNS服务器完成,其过程可简单描述为:域名地址经过DNS服务器解析后,得到对应的IP地址,通过该IP地址访问到服务器获取我们要访问的内容。

 

2,Android DNS模块

Android Dns模块代码:

bionic/libc/netbsd/*

 

DNS请求的入口函数:

Int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)

 

3,Android DNS请求机制

3.1,查询方式顺序

getaddrinfo() {
    _files_getaddrinfo()	//从文件/system/etc/hosts中查询域名地址
    _dns_getaddrinfo()	//向DNS缓存或者DNS服务器查询域名地址
}
_dns_getaddrinfo() {
    _resolv_cache_lookup()	//向DNS缓存中查询
    send_dg()	//像DNS服务器查询
}

 

3.2,4A和A

Type为4A的dns请求,代表请求域名的IPV6地址

Type为A的dns请求,代表请求域名的IPV4地址

 

Android设备IPV6单栈的情况(获取了有效的IPV6地址):对域名进行type为4A的dns请求

Android设备IPV4单栈的情况(获取了有效的IPV4地址):对域名进行type为A的dns请求

Android设备IPV6和IPV4双栈的情况(同时获取了有效的IPV6和IPV4地址):对域名分别进行type为4A和A的dns请求,4A的dns请求优先发出

 

3.3,DNS请求的目的地址

DNS请求的目的地址也就是DNS服务器地址,Android设备的DNS服务器地址根据不同的interface(eth0,wlan0等)来管理,以eth0为例:

情景1:

IPV4先连接成功,IPV6后连接成功

这种情况下IPV4的DNS服务器地址会先设置到DNS模块的DNS地址数组中,IPV6的DNS服务器地址则会滞后,保存顺序如下:

DNS_ADDR_LIST[0] = IPV4.DNS1

DNS_ADDR_LIST[1] = IPV4.DNS2

DNS_ADDR_LIST[2] = IPV6.DNS1

情景2:

IPV6先连接成功,IPV4后连接成功

这种情况下IPV6的DNS服务器地址会先设置到DNS模块的DNS地址数组中,IPV4的DNS服务器地址则会滞后,保存顺序如下:

DNS_ADDR_LIST[0] = IPV6.DNS1

DNS_ADDR_LIST[1] = IPV6.DNS2

DNS_ADDR_LIST[2] = IPV4.DNS1

 

Android系统DNS模块中默认MAXNS(最多保存DNS服务器地址个数)等于3

 

也就是说最多向3个DNS服务器发起域名解析请求(前2个DNS服务器都无法成功解析时)

请求过程如下:

{

    Send request to DNS_ADDR_LIST[0]

    If(ok)

        return

    else

    {

        Send request to DNS_ADDR_LIST[1]

        If(ok)

            return

        else

            Send request to DNS_ADDR_LIST[2]

    }

}

 

3.4,DNS请求retry和timeout机制

Android dns每次请求等待DNS服务器响应都有timeout时间,超时或者接收到的response不正确则会有retry机制

默认的retry设置是2,也就是说有2次请求机会

每次等待DNS服务器响应的timeout时间基数是5s,实际的timeout时间会根据这个基数和当前请求的dns服务器地址index做一个计算来求出本次等待的timeout时间

 

 

 

4,Android DNS请求流程

业务调用一次getaddrinfo函数进行DNS域名解析流程如下:

getaddrinfo() {

    res = _files_getaddrinfo(); // 文件查找,查找成功则getaddrinfo结束

    If(res == ok)

        return;

    _dns_getaddrinfo() { // 向DNS缓存或者DNS服务器查询域名地址

        for type in [4A,A]

        {

            send_request(type) {

                res = _resolv_cache_lookup(); //向DNS缓存中查询

                If(res == ok)

                    return; //send_request()结束

                send_dg() { //向DNS服务器查询

                    for retry in [1,2]

                    {

                        for dns in [dns1,dns2,dns3]

                        {

                            send request to dns

                            If(ok)

                                return;  //send_dg()结束

                        }

                    }

                }

            }

        }

    }

}

总结:

业务调用一次getaddrinfo函数进行dns解析请求流程如下:

  1. 首先从文件/system/etc/hosts中查询域名对应地址,若查找成功则结束
  2. 文件中未查询成功,则准备发送dns解析请求,如果ipv6地址存在,则优先发送type为4A的请求
  3. 发送4A请求前先查询DNS缓存,若缓存中查找成功,则结束4A请求,准备进行发送type为A的请求
  4. 若缓存查找失败,则向DNS服务器列表中的第一个DNS服务器地址发出第一次4A请求,收到服务器response且查询成功则结束4A请求,准备发送type为A的请求
  5. 若未接收到服务器response或查询失败,则向DNS服务器列表中的第二个DNS服务器地址发出第一次4A请求,收到服务器response且查询成功则结束4A请求,准备发送type为A的请求
  6. 若DNS服务器列表中3个服务器地址的4A请求都超时或者失败,则重新从第一个服务器地址开始发送第二次4A请求,直到查询成功后结束4A请求,若3个服务器地址的第二次4A请求都未成功,则4A请求查询结果为失败,准备发送type未A的请求
  7. A请求过程与4A一样的循环方式
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值