IO.js DNS

2018-11-28 22:33 更新

穩(wěn)定度: 2 - 穩(wěn)定

通過(guò)require('dns')來(lái)獲取這個(gè)模塊。

這個(gè)模塊包含以下兩類函數(shù):

1) 使用底層操作系統(tǒng)工具來(lái)進(jìn)行域名解析的函數(shù),并且不需要進(jìn)行任何網(wǎng)絡(luò)活動(dòng)。這類函數(shù)只有一個(gè):dns.lookup。希望與 在其他操作系統(tǒng)的其他應(yīng)用 執(zhí)行域名解析 有相同行為時(shí),請(qǐng)使用dns.lookup。

下面是一個(gè)解析www.google.com的例子:

var dns = require('dns');

dns.lookup('www.google.com', function onLookup(err, addresses, family) {
  console.log('addresses:', addresses);
});

2) 連接實(shí)際的DNS服務(wù)器來(lái)進(jìn)行域名解析的函數(shù),并且經(jīng)常使用網(wǎng)絡(luò)來(lái)執(zhí)行DNS查找。除了dns.lookupDNS模塊的所有函數(shù)都屬于這類。這類函數(shù)不與dns.lookup使用相同的配置文件。例如,它們不使用/etc/hosts配置文件。這類函數(shù)適合那些不希望使用底層操作系統(tǒng)工具來(lái)進(jìn)行域名解析,總是想要執(zhí)行DNS查詢的開(kāi)發(fā)者。

下面例子是,解析'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));
    });
  });
});

兩者之間的選擇會(huì)產(chǎn)生微妙的結(jié)果,更多信息請(qǐng)查詢下文實(shí)現(xiàn)注意事項(xiàng)章節(jié)。

dns.lookup(hostname[, options], callback)

解析hostname(如'google.com')為第一個(gè)找到的A(IPv4)或AAAA(IPv6)記錄。options可以是對(duì)象或者數(shù)組。如果options沒(méi)有提供,那么IPv4和IPv6都是有效的。如果options是一個(gè)數(shù)組,那么它必須是46。

另外,options可以是一個(gè)含有以下屬性的對(duì)象:

  • family: {Number} - 地址族。如果提供,必須為整數(shù)46。如果沒(méi)有提供,那么IPv4和IPv6都是有效的。
  • hints: {Number} - 如果提供,它必須是一個(gè)或多個(gè)支持的getaddrinfo標(biāo)識(shí)。如果沒(méi)有提供,那么沒(méi)有標(biāo)識(shí)被傳遞給getaddrinfo。多個(gè)標(biāo)識(shí)可以通過(guò)在邏輯上ORing它們的值,來(lái)傳遞給hints。支持的getaddrinfo標(biāo)識(shí)請(qǐng)參閱下文。
  • all: {Boolean} - 如果true,那么回調(diào)函數(shù)以數(shù)組的形式返回所有解析的地址,否則只返回一個(gè)地址。默認(rèn)為false。

所有的屬性都是可選的,以下是一個(gè)options例子:

{
  family: 4,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
  all: false
}

回調(diào)函數(shù)有參數(shù)(err, address, family)。address是IPv4或IPv6地址字符串。familyadress的協(xié)議族,即46。

如果options的所有參數(shù)都被設(shè)置,那么參數(shù)轉(zhuǎn)變?yōu)椋╡rr, addresses),addresses是一個(gè)地址和協(xié)議族數(shù)組。

若發(fā)生錯(cuò)誤,err是錯(cuò)誤對(duì)象,err.code是錯(cuò)誤碼。不僅在hostname不存在時(shí),在如沒(méi)有可用的文件描述符等情況下查找失敗,err.code也會(huì)被設(shè)置為'ENOENT'

dns.lookup不需要與DNS協(xié)議有任何關(guān)系。它僅僅是一個(gè)連接名字和地址的操作系統(tǒng)功能。

在任何的io.js程序中,它的實(shí)現(xiàn)對(duì)表現(xiàn)有一些微妙但是重要的影響。在使用前,請(qǐng)花一些時(shí)間查閱實(shí)現(xiàn)注意事項(xiàng)章節(jié)。

dns.lookupService(address, port, callback)

解析給定的addressport為一個(gè)主機(jī)名和使用getnameinfo的服務(wù)。

回調(diào)函數(shù)有參數(shù)(err, hostname, service)。hostnameservice參數(shù)是字符串(如分別為'localhost''http')。

若發(fā)生錯(cuò)誤,err是錯(cuò)誤對(duì)象,err.code是錯(cuò)誤碼。

dns.resolve(hostname[, rrtype], callback)

使用指定的rrtype類型,解析主機(jī)名(如'google.com')為一個(gè)記錄數(shù)組。

有效的rrtype有:

  • 'A' (IPV4 地址,默認(rèn))
  • 'AAAA' (IPV6 地址)
  • 'MX' (郵件交換記錄)
  • 'TXT' (文本記錄)
  • 'SRV' (SRV記錄)
  • 'PTR' (用于IP反向查找)
  • 'NS' (域名服務(wù)器記錄)
  • 'CNAME' (別名記錄)
  • 'SOA' (權(quán)限開(kāi)始記錄)

回調(diào)函數(shù)有參數(shù)(err, addresses)。address中每個(gè)元素的類型由記錄類型所指定,并且在下文相應(yīng)的查找方法中有描述。

若發(fā)生錯(cuò)誤,err是錯(cuò)誤對(duì)象,err.code是下文錯(cuò)誤代碼列表中的一個(gè)。

dns.resolve4(hostname, callback)

dns.resolve()相同,但只使用IPv4查詢(一個(gè)記錄)。地址是一個(gè)IPv4地址數(shù)組(如['74.125.79.104', '74.125.79.105', '74.125.79.106'])。

dns.resolve6(hostname, callback)

dns.resolve4()相同,除了使用IPv6查詢(一個(gè)AAAA查詢)。

dns.resolveMx(hostname, callback)

dns.resolve()相同,但是只用于郵件交換查詢(MX記錄)。

地址是一個(gè)MX記錄數(shù)組,每一個(gè)元素都有一個(gè)priority和一個(gè)exchange屬性(如[{'priority': 10, 'exchange': 'mx.example.com'},...])。

dns.resolveTxt(hostname, callback)

dns.resolve()相同,但是只用于文本查詢(TXT記錄)。地址是一個(gè)hostname可用的2-d數(shù)組(如[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。每個(gè)字?jǐn)?shù)組包含一個(gè)記錄的TXT數(shù)據(jù)塊。根據(jù)使用場(chǎng)景的不同,它們可能被連接在一起也可能被分開(kāi)。

dns.resolveSrv(hostname, callback)

dns.resolve()相同,但是只用于服務(wù)查詢(SRV記錄)。地址是一個(gè)hostname可用的SRV記錄數(shù)組。SRV記錄的屬性有priority,weight,port,和name(如[{'priority': 10, 'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...])。

dns.resolveSoa(hostname, callback)

dns.resolve()相同,但是只用于權(quán)限記錄查詢(SOA記錄)。

地址是一個(gè)有以下結(jié)構(gòu)的對(duì)象:

{
  nsname: 'ns.example.com',
  hostmaster: 'root.example.com',
  serial: 2013101809,
  refresh: 10000,
  retry: 2400,
  expire: 604800,
  minttl: 3600
}

dns.resolveNs(hostname, callback)

dns.resolve()相同,但是只用于域名服務(wù)器查詢(NS記錄)。地址是一個(gè)hostname可用的域名服務(wù)器記錄數(shù)組(如['ns1.example.com', 'ns2.example.com'])。

dns.resolveCname(hostname, callback)

dns.resolve()相同,但是只用于別名記錄(別名記錄)。地址是一個(gè)hostname可用的別名數(shù)組(如['bar.example.com'])。

dns.reverse(ip, callback)

為得到一個(gè)主機(jī)名數(shù)組,反向查詢一個(gè)IP。

回調(diào)函數(shù)有參數(shù)(err, hostnames)。

若發(fā)生錯(cuò)誤,err是錯(cuò)誤對(duì)象,err.code是下文錯(cuò)誤代碼列表中的一個(gè)。

dns.getServers()

返回一個(gè)正在被用于解析的IP地址字符串?dāng)?shù)組。

dns.setServers(servers)

給定一個(gè)IP地址字符串?dāng)?shù)組,將它們?cè)O(shè)置給用來(lái)解析的服務(wù)器。

如果你為地址指定了一個(gè)端口,端口會(huì)被忽略,因?yàn)榈讓訋?kù)不支持。

如果你傳遞了非法輸入,會(huì)拋出錯(cuò)誤。

Error codes

每一次DNS查詢都可能返回以下錯(cuò)誤碼之一:

  • dns.NODATA: DNS服務(wù)器返回一個(gè)沒(méi)有數(shù)據(jù)的應(yīng)答。
  • dns.FORMERR: DNS服務(wù)器聲明查詢是格式錯(cuò)誤的。
  • dns.SERVFAIL: DNS服務(wù)器返回一個(gè)普通錯(cuò)誤。
  • dns.NOTFOUND: 域名沒(méi)有找到。
  • dns.NOTIMP: DNS服務(wù)器沒(méi)有實(shí)現(xiàn)請(qǐng)求的操作。
  • dns.REFUSED: DNS服務(wù)器拒絕查詢。
  • dns.BADQUERY: 格式錯(cuò)誤的DNS查詢。
  • dns.BADNAME: 格式錯(cuò)誤的主機(jī)名。
  • dns.BADFAMILY: 不支持的協(xié)議族。
  • dns.BADRESP: 格式錯(cuò)誤的DNS響應(yīng)。
  • dns.CONNREFUSED: 不能連接到DNS服務(wù)器。
  • dns.TIMEOUT: 連接DNS服務(wù)器超時(shí)。
  • dns.EOF: 文件末端。
  • dns.FILE: 讀取文件錯(cuò)誤。
  • dns.NOMEM: 內(nèi)存溢出。
  • dns.DESTRUCTION: 通道被銷毀。
  • dns.BADSTR: 格式錯(cuò)誤的字符串。
  • dns.BADFLAGS: 指定了非法標(biāo)志。
  • dns.NONAME: 給定的主機(jī)名不是數(shù)字。
  • dns.BADHINTS: 給定的提示標(biāo)識(shí)非法。
  • dns.NOTINITIALIZED: c-ares庫(kù)初始化未被執(zhí)行。
  • dns.LOADIPHLPAPI: 加載iphlpapi.dll錯(cuò)誤。
  • dns.ADDRGETNETWORKPARAMS: 找不到GetNetworkParams函數(shù)。
  • dns.CANCELLED: DNS查詢被取消。

支持的getaddrinfo標(biāo)識(shí)

以下標(biāo)識(shí)可以被傳遞給dns.lookuphints

  • dns.ADDRCONFIG: 返回的地址類型由當(dāng)前系統(tǒng)支持的地址類型決定。例如,如果當(dāng)前系統(tǒng)至少有一個(gè)IPv4地址被配置,那么將只會(huì)返回IPv4地址?;厮莸刂凡槐豢紤]。
  • dns.V4MAPPED: 如果IPv6協(xié)議族被指定,但是沒(méi)有發(fā)現(xiàn)IPv6地址,那么返回IPv6地址的IPv4映射。

實(shí)現(xiàn)注意事項(xiàng)

盡管dns.lookupdns.resolve*/dns.reverse函數(shù)都用于關(guān)聯(lián)一個(gè)域名和一個(gè)地址(或反之亦然),它們的行為還是有些許區(qū)別。這些差別雖然微小,但是對(duì)于io.js程序的行為有重大影響。

dns.lookup

在引擎下,dns.lookup使用了和其他程序相同的操作系統(tǒng)功能。例如,dns.lookup將總是和ping命令一樣解析一個(gè)給定的域名。在大多類POSIX操作系統(tǒng)上,dns.lookup函數(shù)的表現(xiàn)可以通過(guò)改變nsswitch.conf(5) 和/或 resolv.conf(5)的設(shè)置來(lái)調(diào)整,但是需要小心的是,改變這些文件將會(huì)影響這個(gè)操作系統(tǒng)上正在運(yùn)行的所有其他程序。

雖然在JavaScript的角度,這個(gè)調(diào)用是異步的,但是它在libuv線程池中的實(shí)現(xiàn)是同步調(diào)用getaddrinfo(3)。因?yàn)閘ibuv線程池有一個(gè)固定的大小,意味著如果getaddrinfo(3)花費(fèi)了太多的時(shí)間,那么其他libuv線程池中的操作(如文件系統(tǒng)操作)會(huì)感覺(jué)到性能下降。為了緩解這個(gè)情況,一個(gè)潛在的解決方案是通過(guò)設(shè)置'UV_THREADPOOL_SIZE'環(huán)境變量大于4(當(dāng)前默認(rèn)值)來(lái)增加libuv線程池的大小。更多l(xiāng)ibuv線程池的信息,請(qǐng)參閱官方的libuv文檔。

dns.resolve,以dns.resolve和dns.reverse開(kāi)頭的函數(shù)

這些函數(shù)的實(shí)現(xiàn)與dns.lookup相當(dāng)不同。它們不使用getaddrinfo(3)并且它們總是通過(guò)網(wǎng)絡(luò)執(zhí)行一次DNS查詢。這些網(wǎng)絡(luò)通信通常是異步的,并且不使用libuv線程池。

作為結(jié)果,其他使用libuv線程池的dns.lookup方法的進(jìn)程可能會(huì)有相同的負(fù)面影響,但這些函數(shù)沒(méi)有。

它們與dns.lookup使用了不同的配置文件。例如,它們不使用/etc/hosts中的配置。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)