稳定性: 3 - 稳定本节将介绍node.js的dns模块,你可以通过调用require('dns')来访问dns模块。
dns模块包含的函数属于2个不同的分类:
1)使用系统底层的特性,完成名字解析,这个过程不需要网络通讯,这个分类仅有一个函数:dns.lookup。开发者在同一个系统里名字解析都是用 dns.lookup。
下面的例子解析了www.google.com:
var dns = require('dns');
dns.lookup('www.google.com', function onlookup(err, addresses, family) {
console.log('addresses:', addresses);
});2)连接到dns服务器进行名字解析,始终使用网络来进行域名查询。这个分类包含除了dns.lookup外的所有函数。这些函数不会和dns.lookup使用同一套配置文件。如果你不想使用系统底层的特性来进行名字解析,而想进行dns查询的话,可以使用这个分类的函数。
下面的例子,解析了'www.google.com',并反向解析返回的ip地址:
var dns = require('dns');
dns.resolve4('www.google.com', function (err, addresses) {
if (err) throw err;
console.log('addresses: ' + json.stringify(addresses));
addresses.foreach(function (a) {
dns.reverse(a, function (err, hostnames) {
if (err) {
throw err;
}
console.log('reverse for ' + a + ': ' + json.stringify(hostnames));
});
});
});更多细节参考implementation considerations section。
将域名(比如'google.com')解析为第一条找到的记录a (ipv4)或aaaa(ipv6)。参数options可以是一个对象或整数。如果没有提供options,ip v4和 v6地址都可以。如果options是整数,则必须是4或6。
options参数可能是包含family和hints两个属性的对象。这两个属性都是可选的。如果提供了family,则必须是4或6,否则,ip v4和v6地址都可以。如果提供了hints,可以是一个或者多个getaddrinfo标志,若不提供,没有标志会传给getaddrinfo。多个标志位可以通过或运算来整合。以下的例子展示如何使用options。
{
family: 4,
hints: dns.addrconfig | dns.v4mapped
}参见supported getaddrinfo flags 查看更多的标志位。
回调函数包含参数 (err, address, family)。address参数表示ip v4或v6地址。family参数是4或6,表示address家族(不一定是之前传入lookup的值)。
出错时,参数err是error对象,err.code是错误代码。请记住,err.code等于'enoent',不仅可能是因为域名不存在,还有可能是是其他原因,比如没有可用文件描述符。
dns.lookup不必和dns协议有关系。它使用了操作系统的特性,能将名字和地址关联。
实现这些东西也许很简单,但是对于 node.js 程序来说都重要,所以在使用前请花点时间阅读implementation considerations section。
使用getnameinfo解析传入的地址和端口为域名和服务。
这个回调函数的参数是(err, hostname, service)。hostname和service都是字符串 (比如'localhost'和'http')。
出错时,参数err是error对象,err.code是错误代码。
将一个域名(如'google.com')解析为一个rrtype指定记录类型的数组。
有效的rrtypes值为:
'a' (ipv4地址,默认)'aaaa' (ipv6地址)'mx' (邮件交换记录)'txt' (text记录)'srv' (srv记录)'ptr' (用来反向ip查找)'ns' (域名服务器记录)'cname' (别名记录)'soa' (授权记录的初始值)回调参数为(err, addresses). 其中addresses中每一项的类型都取决于记录类型,详见下文对应的查找方法。
出错时,参数err是 error 对象,err.code是错误代码。
和dns.resolve()类似,仅能查询ipv4 (a记录)。addressesipv4地址数组 (比如,['74.125.79.104', '74.125.79.105', '74.125.79.106'])。
和dns.resolve4()类似,仅能查询 ipv4(aaaa查询)。
和dns.resolve()类似,仅能查询邮件交换(mx记录)。
addresses是mx记录数组,每一个包含优先级和交换属性(比如,[{'priority': 10, 'exchange': 'mx.example.com'},...])。
和dns.resolve()类似,仅能进行文本查询 (txt记录)。addresses是2-d文本记录数组。(比如,[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。每个子数组包含一条记录的txt块。根据使用情况可以连接在一起,也可单独使用。
和dns.resolve()类似,仅能进行服务记录查询 (srv记录)。addresses是hostname可用的srv记录数组。srv记录属性有优先级(priority),权重(weight), 端口(port), 和名字(name) (比如,[{'priority': 10, 'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...])。
和dns.resolve()类似,仅能查询权威记录(soa记录)。
addresses是包含以下结构的对象:
{
nsname: 'ns.example.com',
hostmaster: 'root.example.com',
serial: 2013101809,
refresh: 10000,
retry: 2400,
expire: 604800,
minttl: 3600
}和dns.resolve()类似,仅能进行域名服务器记录查询(ns记录)。addresses是域名服务器记录数组(hostname可以使用) (比如,['ns1.example.com', 'ns2.example.com'])。
和dns.resolve()类似,仅能进行别名记录查询 (cname记录)。addresses是对hostname可用的别名记录数组 (比如,['bar.example.com'])。
反向解析ip地址,返回指向该ip地址的域名数组。
回调函数参数(err, hostnames)。
出错时,参数err是error对象,err.code是错误代码。
返回一个用于当前解析的ip地址的数组的字符串。
指定一组ip地址作为解析服务器。
如果你给地址指定了端口,端口会被忽略,因为底层库不支持。
传入无效参数,会抛出以下错误:
每个dns查询都可能返回以下错误:
dns.nodata: dns服务器返回无数据应答。 dns.formerr: dns服务器声称查询格式错误。 dns.servfail: dns服务器返回一般失败。 dns.notfound: 没有找到域名。 dns.notimp: dns服务器未实现请求的操作。 dns.refused: dns服务器拒绝查询。 dns.badquery: dns查询格式错误。 dns.badname: 域名格式错误。 dns.badfamily: 地址协议不支持。 dns.badresp: dns回复格式错误。 dns.connrefused: 无法连接到dns服务器。 dns.timeout: 连接dns服务器超时。 dns.eof: 文件末端。 dns.file: 读文件错误。 dns.nomem: 内存溢出。 dns.destruction: 通道被摧毁。 dns.badstr: 字符串格式错误。 dns.badflags: 非法标识符。 dns.noname: 所给主机不是数字。 dns.badhints: 非法hints标识符。 dns.notinitialized: c c-ares库尚未初始化。 dns.loadiphlpapi: 加载iphlpapi.dll出错。 dns.addrgetnetworkparams: 无法找到getnetworkparams函数。 dns.cancelled: 取消dns查询。 以下内容可作为hints标志传给dns.lookup
dns.addrconfig: 返回当前系统支持的地址类型。例如,如果当前系统至少配置了一个ipv4地址,则返回ipv4地址。dns.v4mapped: 如果指定了ipv6家族, 但是没有找到ipv6地址,将返回ipv4映射的ipv6地址。虽然dns.lookup和dns.resolve*/dns.reverse函数都能实现网络名和网络地址的关联,但是他们的行为不太一样。这些不同点虽然很巧妙,但是会对node.js程序产生显著的影响。
dns.lookup和绝大多数程序一样使用了相同的系统特性。例如,dns.lookup和ping命令用相同的方法解析了一个指定的名字。多数类似posix的系统,dns.lookup函数可以通过改变nsswitch.conf(5)和/或resolv.conf(5)的设置调整。如果改变这些文件将会影响系统里的其他应用。
虽然,javascript调用是异步的,它的实现是同步的调用libuv线程池里的getaddrinfo(3)。因为libuv线程池固定大小,所以如果调用getaddrinfo(3) 的时间太长,会使的池里的其他操作(比如文件操作)性能降低。为了降低这个风险,可以通过增加'uv_threadpool_size'的值,让它超过4,来调整libuv线程池大小,更多信息参见[the official libuvdocumentation](http://docs.libuv.org/en/latest/threadpool.html)。
这些函数的实现和dns.lookup不大相同。他们不会用到getaddrinfo(3),而是始终进行网络查询。这些操作都是异步的,和libuv线程池无关。
因此,这些操作对于其他线程不会产生负面影响,这和dns.lookup不同。
它们不会用到dns.lookup的配置文件(例如 ,/etc/hosts_)。