libcurl 是一个很强大的开源网络处理库,主要功能就是用不同的协议连接和沟通不同的服务器。
目前支持 http、https、ftp、gopher、telnet、dict、file 和 ldap 等协议。
libcurl 同样支持 HTTPS 证书授权,HTTP POST、HTTP PUT、FTP 上传,HTTP 基本表单上传、代理、cookies 和用户认证等功能。Google Chrome 内核就用到了 libcurl 库。
c-ares是一个C语言实现的DNS非阻塞异步解析库,libcurl、 libevent、 gevent,、nodejs和 wireshark都使用了c-ares,因此在一般开发一些服务的客户端Client,在连接服务器Server时,需要做的工作的就是域名解析。
客户端使用c-ares作为DNS解析库,但是当电脑DN地址发生变更时客户端并没有感知到,依然使用变更前的DNS地址做目标域名的解析,会是什么原因?
可能是因为c-ares库缓存了之前的DNS解析结果,导致客户端仍然使用旧的DNS地址进行解析。
c-ares库会在解析DNS时使用缓存来提高解析速度,并且缓存的生命周期是有限的。
如果缓存的生命周期还没有结束,c-ares库就会使用缓存中的DNS地址进行解析。
可以尝试清除c-ares的缓存或者重新初始化c-ares库来解决这个问题。
另外,建议客户端定期更新DNS缓存或者使用DNS服务器提供的TTL机制来自动更新DNS缓存。
如何解决这个问题?
解决这个问题的方法有以下几种:
在使用c-ares的代码中添加对DNS地址变更的监听,当检测到DNS地址变更时,清空c-ares的缓存,并重新初始化c-ares。这样可以确保c-ares使用最新的DNS地址进行解析。
在客户端的网络配置中正确设置DNS地址,确保DNS地址变更后客户端可以正确地使用新的DNS地址进行解析。
客户端可以定期检查DNS地址是否发生变更,如果发生变更,则清空c-ares的缓存,并重新初始化c-ares。这样可以确保c-ares使用最新的DNS地址进行解析。
如果客户端无法及时获取DNS地址变更的通知,则可以在客户端代码中添加定时器,定期检查DNS地址是否发生变更,并更新c-ares的DNS地址。
通过上述方法,可以确保c-ares能够正确地使用最新的DNS地址进行解析,避免出现DNS解析错误的问题。
当电脑DNS地址发生变更时,客户端并没有感知到依然使用变更前的DNS地址做目标域名的解析,超时时间是多少?
c-ares库的DNS解析超时时间是可以配置的,一般默认为5秒。
如果在这个超时时间内没有收到DNS响应,c-ares库会返回一个错误码,表示DNS解析失败。
如果客户端依然使用旧的DNS地址进行解析,那么解析会一直等待,直到超时时间到达。
在超时时间内,如果DNS服务器没有响应,客户端会一直等待,直到超时时间到达。
如果超时时间到达,c-ares库会返回一个错误码,表示DNS解析失败。
在实际使用中,为了避免DNS解析错误和超时错误,可以通过调整超时时间和优化DNS解析缓存等方式来提高解析效率和可靠性。
为什么在mac电脑上超时时间高达30秒?
c-ares库的DNS解析超时时间是可以通过参数进行配置的,一般默认为5秒。
但是在macOS系统上,由于系统的默认DNS解析超时时间为30秒,因此c-ares库也会继承这个超时时间。
如果需要修改c-ares库的DNS解析超时时间,可以通过设置CARES_TIMEOUTMS_DEFAULT
宏定义来修改默认的超时时间。
例如,将超时时间设置为10秒,可以在编译时添加如下宏定义:
-D CARES_TIMEOUTMS_DEFAULT=10000
这样就可以将c-ares库的默认DNS解析超时时间修改为10秒。
使用c-ares的客户端,当所在电脑主DNS挂了,多久会切到从DNS做解析?
使用c-ares的客户端在解析域名时,会按照操作系统的DNS解析规则进行解析。
一般情况下,操作系统会先尝试使用主DNS服务器进行解析,如果主DNS服务器无法响应或者响应超时,则会尝试使用备用DNS服务器进行解析。
在Windows系统中,DNS解析的默认超时时间为2秒,如果在这个时间内无法获得响应,则会尝试使用备用DNS服务器进行解析。
在Linux系统中,DNS解析的默认超时时间为5秒,如果在这个时间内无法获得响应,则会尝试使用备用DNS服务器进行解析。
因此,当主DNS服务器挂掉时,客户端会在一定的超时时间后尝试使用备用DNS服务器进行解析。
如果备用DNS服务器也无法响应,则会继续尝试其他备用DNS服务器,直到获得响应或者所有备用DNS服务器都无法响应为止。
在使用c-ares的客户端中,可以通过调整DNS解析超时时间和优化DNS解析缓存等方式来提高解析效率和可靠性。
用node内置dns模块,替代 libcurl 的c-ares 做DNS解析
你可以使用 Node.js 内置的 dns
模块来替代 libcurl 的 c-ares 库进行 DNS 解析。
Node.js 的 dns
模块提供了多个方法来进行 DNS 查询,包括 dns.lookup()
、dns.resolve()
、dns.reverse()
等,可以满足大部分的 DNS 解析需求。
与 c-ares 不同,Node.js 的 dns
模块是基于系统的 DNS 解析机制实现的,因此可以直接使用系统的 DNS 缓存和 DNS 配置,无需单独管理 DNS 缓存和 DNS 配置。同时,Node.js 的 dns
模块也支持异步查询和回调函数,可以满足高并发的网络请求需求。
以下是一个使用 Node.js dns
模块进行 DNS 解析的示例代码:
const dns = require('dns');
// 解析域名为 IP 地址
dns.lookup('www.example.com', (err, address, family) => {
if (err) throw err;
console.log(`IP 地址: ${address}`);
});
// 解析域名为 IPv4 地址
dns.resolve4('www.example.com', (err, addresses) => {
if (err) throw err;
console.log(`IPv4 地址: ${JSON.stringify(addresses)}`);
});
// 解析域名为 IPv6 地址
dns.resolve6('www.example.com', (err, addresses) => {
if (err) throw err;
console.log(`IPv6 地址: ${JSON.stringify(addresses)}`);
});
// 查询邮件交换器记录
dns.resolveMx('example.com', (err, records) => {
if (err) throw err;
console.log(`MX 记录: ${JSON.stringify(records)}`);
});
// 解析 IP 地址为域名
dns.reverse('8.8.8.8', (err, hostnames) => {
if (err) throw err;
console.log(`域名: ${JSON.stringify(hostnames)}`);
});
需要注意的是,Node.js dns
模块的查询结果可能与 c-ares 的查询结果不完全相同,因为它们使用的 DNS 解析机制不同。
如果需要完全替代 c-ares 进行 DNS 解析,可以使用第三方的 DNS 解析库,例如 dns.js
、native-dns
等。
参考
curl
https://curl.haxx.se
libcurl
https://curl.haxx.se/libcurl
libcurl官方教程
https://curl.haxx.se/libcurl/c/libcurl-tutorial.html
libcurl 使用教程
https://getiot.tech/zh/awesome/awesome-c/libcurl
curl的25年之旅(译)
https://juejin.cn/post/7238804998276137020
为什么我们经常遇到curl域名解析超时?
https://toutiao.io/posts/sevo1kc/preview
c-ares 一个C语言的异步DNS解析库
http://wangxuemin.github.io/2015/07/31/c-ares%20%E4%B8%80%E4%B8%AAC%E8%AF%AD%E8%A8%80%E7%9A%84%E5%BC%82%E6%AD%A5DNS%E8%A7%A3%E6%9E%90%E5%BA%93/
CURLOPT_DNS_CACHE_TIMEOUT explained
https://curl.se/libcurl/c/CURLOPT_DNS_CACHE_TIMEOUT.html