Node.js DNS

2022-02-26 10:31 更新
穩(wěn)定性: 3 - 穩(wěn)定

本節(jié)將介紹Node.js的DNS模塊,你可以通過調(diào)用require('dns')來訪問DNS模塊。

DNS模塊包含的函數(shù)屬于2個不同的分類:

1)使用系統(tǒng)底層的特性,完成名字解析,這個過程不需要網(wǎng)絡(luò)通訊,這個分類僅有一個函數(shù):dns.lookup。開發(fā)者在同一個系統(tǒng)里名字解析都是用 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服務(wù)器進(jìn)行名字解析,始終使用網(wǎng)絡(luò)來進(jìn)行域名查詢。這個分類包含除了dns.lookup外的所有函數(shù)。這些函數(shù)不會和dns.lookup使用同一套配置文件。如果你不想使用系統(tǒng)底層的特性來進(jìn)行名字解析,而想進(jìn)行DNS查詢的話,可以使用這個分類的函數(shù)。

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

更多細(xì)節(jié)參考Implementation considerations section。

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

將域名(比如'google.com')解析為第一條找到的記錄A (IPV4)或AAAA(IPV6)。參數(shù)options可以是一個對象或整數(shù)。如果沒有提供options,IP v4和 v6地址都可以。如果options是整數(shù),則必須是46。

options參數(shù)可能是包含familyhints兩個屬性的對象。這兩個屬性都是可選的。如果提供了family,則必須是46,否則,IP v4和v6地址都可以。如果提供了hints,可以是一個或者多個getaddrinfo標(biāo)志,若不提供,沒有標(biāo)志會傳給getaddrinfo。多個標(biāo)志位可以通過或運算來整合。以下的例子展示如何使用options

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

參見supported getaddrinfo flags 查看更多的標(biāo)志位。

回調(diào)函數(shù)包含參數(shù) (err, address, family)。address參數(shù)表示IP v4或v6地址。family參數(shù)是4或6,表示address家族(不一定是之前傳入lookup的值)。

出錯時,參數(shù)errError對象,err.code是錯誤代碼。請記住,err.code等于'ENOENT',不僅可能是因為域名不存在,還有可能是是其他原因,比如沒有可用文件描述符。

dns.lookup不必和DNS協(xié)議有關(guān)系。它使用了操作系統(tǒng)的特性,能將名字和地址關(guān)聯(lián)。

實現(xiàn)這些東西也許很簡單,但是對于 Node.js 程序來說都重要,所以在使用前請花點時間閱讀Implementation considerations section。

dns.lookupService(address, port, callback)

使用getnameinfo解析傳入的地址和端口為域名和服務(wù)。

這個回調(diào)函數(shù)的參數(shù)是(err, hostname, service)。hostnameservice都是字符串 (比如'localhost''http')。

出錯時,參數(shù)errError對象,err.code是錯誤代碼。

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

將一個域名(如'google.com')解析為一個rrtype指定記錄類型的數(shù)組。

有效的rrtypes值為:

  • 'A' (IPV4地址,默認(rèn))
  • 'AAAA' (IPV6地址)
  • 'MX' (郵件交換記錄)
  • 'TXT' (text記錄)
  • 'SRV' (SRV記錄)
  • 'PTR' (用來反向IP查找)
  • 'NS' (域名服務(wù)器記錄)
  • 'CNAME' (別名記錄)
  • 'SOA' (授權(quán)記錄的初始值)

回調(diào)參數(shù)為(err, addresses). 其中addresses中每一項的類型都取決于記錄類型,詳見下文對應(yīng)的查找方法。

出錯時,參數(shù)errError 對象,err.code是錯誤代碼。

dns.resolve4(hostname, callback)

dns.resolve()類似,僅能查詢IPv4 (A記錄)。addressesIPv4地址數(shù)組 (比如,['74.125.79.104', '74.125.79.105', '74.125.79.106'])。

dns.resolve6(hostname, callback)

dns.resolve4()類似,僅能查詢 IPv4(AAAA查詢)。

dns.resolveMx(hostname, callback)

dns.resolve()類似,僅能查詢郵件交換(MX記錄)。

addresses是MX記錄數(shù)組,每一個包含優(yōu)先級和交換屬性(比如,[{'priority': 10, 'exchange': 'mx.example.com'},...])。

dns.resolveTxt(hostname, callback)

dns.resolve()類似,僅能進(jìn)行文本查詢 (TXT記錄)。addresses是2-d文本記錄數(shù)組。(比如,[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。每個子數(shù)組包含一條記錄的TXT塊。根據(jù)使用情況可以連接在一起,也可單獨使用。

dns.resolveSrv(hostname, callback)

dns.resolve()類似,僅能進(jìn)行服務(wù)記錄查詢 (SRV記錄)。addresseshostname可用的SRV記錄數(shù)組。SRV記錄屬性有優(yōu)先級(priority),權(quán)重(weight), 端口(port), 和名字(name) (比如,[{'priority': 10, 'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...])。

dns.resolveSoa(hostname, callback)

dns.resolve()類似,僅能查詢權(quán)威記錄(SOA記錄)。

addresses是包含以下結(jié)構(gòu)的對象:

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

dns.resolveNs(hostname, callback)

dns.resolve()類似,僅能進(jìn)行域名服務(wù)器記錄查詢(NS記錄)。addresses是域名服務(wù)器記錄數(shù)組(hostname可以使用) (比如,['ns1.example.com', 'ns2.example.com'])。

dns.resolveCname(hostname, callback)

dns.resolve()類似,僅能進(jìn)行別名記錄查詢 (CNAME記錄)。addresses是對hostname可用的別名記錄數(shù)組 (比如,['bar.example.com'])。

dns.reverse(ip, callback)

反向解析IP地址,返回指向該IP地址的域名數(shù)組。

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

出錯時,參數(shù)errError對象,err.code是錯誤代碼。

dns.getServers()

返回一個用于當(dāng)前解析的IP地址的數(shù)組的字符串。

dns.setServers(servers)

指定一組IP地址作為解析服務(wù)器。

如果你給地址指定了端口,端口會被忽略,因為底層庫不支持。

傳入無效參數(shù),會拋出以下錯誤:

Error codes

每個DNS查詢都可能返回以下錯誤:

  • dns.NODATA: DNS服務(wù)器返回?zé)o數(shù)據(jù)應(yīng)答。
  • dns.FORMERR: DNS服務(wù)器聲稱查詢格式錯誤。
  • dns.SERVFAIL: DNS服務(wù)器返回一般失敗。
  • dns.NOTFOUND: 沒有找到域名。
  • dns.NOTIMP: DNS服務(wù)器未實現(xiàn)請求的操作。
  • dns.REFUSED: DNS服務(wù)器拒絕查詢。
  • dns.BADQUERY: DNS查詢格式錯誤。
  • dns.BADNAME: 域名格式錯誤。
  • dns.BADFAMILY: 地址協(xié)議不支持。
  • dns.BADRESP: DNS回復(fù)格式錯誤。
  • dns.CONNREFUSED: 無法連接到DNS服務(wù)器。
  • dns.TIMEOUT: 連接DNS服務(wù)器超時。
  • dns.EOF: 文件末端。
  • dns.FILE: 讀文件錯誤。
  • dns.NOMEM: 內(nèi)存溢出。
  • dns.DESTRUCTION: 通道被摧毀。
  • dns.BADSTR: 字符串格式錯誤。
  • dns.BADFLAGS: 非法標(biāo)識符。
  • dns.NONAME: 所給主機不是數(shù)字。
  • dns.BADHINTS: 非法HINTS標(biāo)識符。
  • dns.NOTINITIALIZED: c c-ares庫尚未初始化。
  • dns.LOADIPHLPAPI: 加載iphlpapi.dll出錯。
  • dns.ADDRGETNETWORKPARAMS: 無法找到GetNetworkParams函數(shù)。
  • dns.CANCELLED: 取消DNS查詢。

支持的 getaddrinfo 標(biāo)志

以下內(nèi)容可作為hints標(biāo)志傳給dns.lookup

  • dns.ADDRCONFIG: 返回當(dāng)前系統(tǒng)支持的地址類型。例如,如果當(dāng)前系統(tǒng)至少配置了一個IPv4地址,則返回IPv4地址。
  • dns.V4MAPPED: 如果指定了IPv6家族, 但是沒有找到IPv6地址,將返回IPv4映射的IPv6地址。

Implementation considerations

雖然dns.lookupdns.resolve*/dns.reverse函數(shù)都能實現(xiàn)網(wǎng)絡(luò)名和網(wǎng)絡(luò)地址的關(guān)聯(lián),但是他們的行為不太一樣。這些不同點雖然很巧妙,但是會對Node.js程序產(chǎn)生顯著的影響。

dns.lookup

dns.lookup和絕大多數(shù)程序一樣使用了相同的系統(tǒng)特性。例如,dns.lookupping命令用相同的方法解析了一個指定的名字。多數(shù)類似POSIX的系統(tǒng),dns.lookup函數(shù)可以通過改變nsswitch.conf(5)和/或resolv.conf(5)的設(shè)置調(diào)整。如果改變這些文件將會影響系統(tǒng)里的其他應(yīng)用。

雖然,JavaScript調(diào)用是異步的,它的實現(xiàn)是同步的調(diào)用libuv線程池里的getaddrinfo(3)。因為libuv線程池固定大小,所以如果調(diào)用getaddrinfo(3) 的時間太長,會使的池里的其他操作(比如文件操作)性能降低。為了降低這個風(fēng)險,可以通過增加'UV_THREADPOOL_SIZE'的值,讓它超過4,來調(diào)整libuv線程池大小,更多信息參見[the official libuvdocumentation](http://docs.libuv.org/en/latest/threadpool.html)。

dns.resolve, functions starting with dns.resolve and dns.reverse

這些函數(shù)的實現(xiàn)和dns.lookup不大相同。他們不會用到getaddrinfo(3),而是始終進(jìn)行網(wǎng)絡(luò)查詢。這些操作都是異步的,和libuv線程池?zé)o關(guān)。

因此,這些操作對于其他線程不會產(chǎn)生負(fù)面影響,這和dns.lookup不同。

它們不會用到dns.lookup的配置文件(例如 ,/etc/hosts_)。


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號