DNS
稳定度: 2 - 稳定
通过require('dns')
来获取这个模块。
这个模块包含以下两类函数:
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查找。除了dns.lookup
外DNS
模块的所有函数都属于这类。这类函数不与dns.lookup
使用相同的配置文件。例如,它们不使用/etc/hosts
配置文件。这类函数适合那些不希望使用底层操作系统工具来进行域名解析,总是想要执行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));
});
});
});
两者之间的选择会产生微妙的结果,更多信息请查询下文实现注意事项
章节。
dns.lookup(hostname[, options], callback)
解析hostname
(如'google.com'
)为第一个找到的A(IPv4)或AAAA(IPv6)记录。options
可以是对象或者数组。如果options
没有提供,那么IPv4和IPv6都是有效的。如果options
是一个数组,那么它必须是4
或6
。
另外,options
可以是一个含有以下属性的对象:
- family: {Number} - 地址族。如果提供,必须为整数
4
或6
。如果没有提供,那么IPv4和IPv6都是有效的。 - hints: {Number} - 如果提供,它必须是一个或多个支持的
getaddrinfo
标识。如果没有提供,那么没有标识被传递给getaddrinfo
。多个标识可以通过在逻辑上ORing
它们的值,来传递给hints
。支持的getaddrinfo
标识请参阅下文。 - all: {Boolean} - 如果
true
,那么回调函数以数组的形式返回所有解析的地址,否则只返回一个地址。默认为false
。
所有的属性都是可选的,以下是一个options
例子:
{
family: 4,
hints: dns.ADDRCONFIG | dns.V4MAPPED,
all: false
}
回调函数有参数(err, address, family)。address
是IPv4或IPv6地址字符串。family
是adress
的协议族,即4
或6
。
如果options
的所有参数都被设置,那么参数转变为(err, addresses),addresses
是一个地址和协议族数组。
若发生错误,err
是错误对象,err.code
是错误码。不仅在hostname
不存在时,在如没有可用的文件描述符等情况下查找失败,err.code
也会被设置为'ENOENT'
。
dns.lookup
不需要与DNS协议有任何关系。它仅仅是一个连接名字和地址的操作系统功能。
在任何的node.js
程序中,它的实现对表现有一些微妙但是重要的影响。在使用前,请花一些时间查阅实现注意事项
章节。
dns.lookupService(address, port, callback)
解析给定的address
和port
为一个主机名和使用getnameinfo
的服务。
回调函数有参数(err, hostname, service)。hostname
和service
参数是字符串(如分别为'localhost'
和'http'
)。
若发生错误,err
是错误对象,err.code
是错误码。
dns.resolve(hostname[, rrtype], callback)
使用指定的rrtype
类型,解析主机名(如'google.com'
)为一个记录数组。
有效的rrtype
有:
- 'A' (IPV4 地址,默认)
- 'AAAA' (IPV6 地址)
- 'MX' (邮件交换记录)
- 'TXT' (文本记录)
- 'SRV' (SRV记录)
- 'PTR' (用于IP反向查找)
- 'NS' (域名服务器记录)
- 'CNAME' (别名记录)
- 'SOA' (权限开始记录)
回调函数有参数(err, addresses)。address
中每个元素的类型由记录类型所指定,并且在下文相应的查找方法中有描述。
若发生错误,err
是错误对象,err.code
是下文错误代码列表中的一个。
dns.resolve4(hostname, callback)
与dns.resolve()
相同,但只使用IPv4查询(一个记录)。地址是一个IPv4地址数组(如['74.125.79.104', '74.125.79.105', '74.125.79.106']
)。
dns.resolve6(hostname, callback)
与dns.resolve4()
相同,除了使用IPv6查询(一个AAAA查询)。
dns.resolveMx(hostname, callback)
与dns.resolve()
相同,但是只用于邮件交换查询(MX记录)。
地址是一个MX记录数组,每一个元素都有一个priority
和一个exchange
属性(如[{'priority': 10, 'exchange': 'mx.example.com'},...]
)。
dns.resolveTxt(hostname, callback)
与dns.resolve()
相同,但是只用于文本查询(TXT记录)。地址是一个hostname
可用的2-d数组(如[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]
)。每个字数组包含一个记录的TXT数据块。根据使用场景的不同,它们可能被连接在一起也可能被分开。
dns.resolveSrv(hostname, callback)
与dns.resolve()
相同,但是只用于服务查询(SRV记录)。地址是一个hostname
可用的SRV记录数组。SRV记录的属性有priority
,weight
,port
,和name
(如[{'priority': 10, 'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...]
)。
dns.resolveSoa(hostname, callback)
与dns.resolve()
相同,但是只用于权限记录查询(SOA记录)。
地址是一个有以下结构的对象:
{
nsname: 'ns.example.com',
hostmaster: 'root.example.com',
serial: 2013101809,
refresh: 10000,
retry: 2400,
expire: 604800,
minttl: 3600
}
dns.resolveNs(hostname, callback)
与dns.resolve()
相同,但是只用于域名服务器查询(NS记录)。地址是一个hostname
可用的域名服务器记录数组(如['ns1.example.com', 'ns2.example.com']
)。
dns.resolveCname(hostname, callback)
与dns.resolve()
相同,但是只用于别名记录(别名记录)。地址是一个hostname
可用的别名数组(如['bar.example.com']
)。
dns.reverse(ip, callback)
为得到一个主机名数组,反向查询一个IP。
回调函数有参数(err, hostnames)。
若发生错误,err
是错误对象,err.code
是下文错误代码列表中的一个。
dns.getServers()
返回一个正在被用于解析的IP地址字符串数组。
dns.setServers(servers)
给定一个IP地址字符串数组,将它们设置给用来解析的服务器。
如果你为地址指定了一个端口,端口会被忽略,因为底层库不支持。
如果你传递了非法输入,会抛出错误。
Error codes
每一次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: 给定的提示标识非法。
- dns.NOTINITIALIZED:
c-ares
库初始化未被执行。 - dns.LOADIPHLPAPI: 加载
iphlpapi.dll
错误。 - dns.ADDRGETNETWORKPARAMS: 找不到
GetNetworkParams
函数。 - dns.CANCELLED: DNS查询被取消。
支持的getaddrinfo标识
以下标识可以被传递给dns.lookup
的hints
:
- dns.ADDRCONFIG: 返回的地址类型由当前系统支持的地址类型决定。例如,如果当前系统至少有一个IPv4地址被配置,那么将只会返回IPv4地址。回溯地址不被考虑。
- dns.V4MAPPED: 如果IPv6协议族被指定,但是没有发现IPv6地址,那么返回IPv6地址的IPv4映射。
实现注意事项
尽管dns.lookup
和dns.resolve*/dns.reverse
函数都用于关联一个域名和一个地址(或反之亦然),它们的行为还是有些许区别。这些差别虽然微小,但是对于node.js
程序的行为有重大影响。
dns.lookup
在引擎下,dns.lookup
使用了和其他程序相同的操作系统功能。例如,dns.lookup
将总是和ping
命令一样解析一个给定的域名。在大多类POSIX操作系统上,dns.lookup
函数的表现可以通过改变nsswitch.conf(5)
和/或 resolv.conf(5)
的设置来调整,但是需要小心的是,改变这些文件将会影响这个操作系统上正在运行的所有其他程序。
虽然在JavaScript
的角度,这个调用是异步的,但是它在libuv线程池中的实现是同步调用getaddrinfo(3)
。因为libuv线程池有一个固定的大小,意味着如果getaddrinfo(3)
花费了太多的时间,那么其他libuv线程池中的操作(如文件系统操作)会感觉到性能下降。为了缓解这个情况,一个潜在的解决方案是通过设置'UV_THREADPOOL_SIZE'
环境变量大于4(当前默认值)来增加libuv线程池的大小。更多libuv线程池的信息,请参阅官方的libuv文档。
dns.resolve,以dns.resolve和dns.reverse开头的函数
这些函数的实现与dns.lookup
相当不同。它们不使用getaddrinfo(3)
并且它们总是通过网络执行一次DNS查询。这些网络通信通常是异步的,并且不使用libuv线程池。
作为结果,其他使用libuv线程池的dns.lookup
方法的进程可能会有相同的负面影响,但这些函数没有。
它们与dns.lookup
使用了不同的配置文件。例如,它们不使用/etc/hosts
中的配置。