Node.js API詳解之 dns模組用法例項分析
本文例項講述了Node.js API詳解之 dns模組用法。分享給大家供大家參考,具體如下:
Node.js API詳解之 dns
dns (域名伺服器)模組包含兩類函式:
第一類函式,使用底層作業系統工具進行域名解析,且無需進行網路通訊。 這類函式只有一個:dns.lookup()。
例子,查詢 baidu.com:
const dns = require('dns'); dns.lookup('www.baidu.com',(err,address,family) => { console.log('IP 地址: %j 地址族: IPv%s',family); }); // IP 地址: "180.149.131.98" 地址族: IPv4
第二類函式,連線到一個真實的 DNS 伺服器進行域名解析,且始終使用網路進行 DNS 查詢。
這類函式包含了 dns 模組中除 dns.lookup() 以外的所有函式。
這些函式使用與 dns.lookup() 不同的配置檔案(例如 /etc/hosts)。
這類函式適合於那些不想使用底層作業系統工具進行域名解析、而是想使用網路進行 DNS 查詢的開發者。
例子,解析 ‘archive.org' 然後逆向解析返回的 IP 地址:
const dns = require('dns'); dns.resolve4('archive.org',addresses) => { if (err) throw err; console.log(`IP 地址: ${JSON.stringify(addresses)}`); addresses.forEach((a) => { dns.reverse(a,hostnames) => { if (err) { throw err; } console.log(`IP 地址 ${a} 逆向解析到域名: ${JSON.stringify(hostnames)}`); }); }); }); // IP 地址: ["207.241.224.2"] // IP 地址 207.241.224.2 逆向解析到域名: ["www.archive.org"]
dns.getServers()
說明:
返回一個用於當前DNF解析的IP地址的陣列的字串,格式根據rfc5952。
如果使用自定義埠,那麼字串將包括一個埠部分。
demo:
const dns= require('dns'); console.log( dns.getServers() ); // [ '172.116.20.254','127.0.0.1' ]
dns.setServers(servers)
說明:
設定IP地址伺服器埠在進行DNS解析時可用,servers引數是一個rfc5952陣列格式的地址。
如果埠是IANA預設埠(53),那麼它可以被忽略。
demo:
const dns = require('dns'); dns.setServers([ '172.116.20.254','127.1.1.1' ]) console.log( dns.getServers() ); // [ '172.116.20.254','127.1.1.1' ]
dns.lookup(hostname[,options],callback)
說明:
解析hostname(例如:'nodejs.org')第一個找到的A(IPv4)或AAAA(IPv6)記錄。
options可以是物件或者整數。如果options沒有被提供,那麼IPv4 和 IPv6都是有效的。如果options是整數,只能是4或6。
另外,options可以是一個含有以下屬性的物件:
family: T地址族。如果提供,必須為整數4或6。如果沒有提供,只接受IPv4和IPv6地址。
all:值為true時, 回撥函式返回一個包含所有解析後地址的陣列,否則只返回一個地址。預設值為false
hints:如果提供,它必須是一個或多個支援的getaddrinfo標識。如果沒有提供,那麼沒有標識被傳遞給getaddrinfo。
多個標識可以通過在邏輯上ORing它們的值,來傳遞給hints。支援的getaddrinfo標識:
dns.ADDRCONFIG: 返回當前系統支援的地址型別。例如,如果當前系統至少配置了一個 IPv4 地址,則返回 IPv4地址。不考慮迴環地址。
dns.V4MAPPED: 如果指定了 IPv6 家族, 但是沒有找到 IPv6 地址,將返回 IPv4 對映的 IPv6地址。在有些作業系統中不支援(e.g FreeBSD 10.1)。
回撥函式包含(err,family)引數。
address是IPv4或IPv6地址字串。
family、是整數4或6,表示地址族(不一定是最初傳遞給查詢的值)。
當all屬性被設定為true時,回撥函式引數變為(err,addresses),addresses則變成一個由address 和 family 屬性組成的物件陣列。
dns.lookup() 不需要與DNS協議有任何關係。它僅僅是一個連線名字和地址的作業系統功能。
在任何的node.js程式中,它的實現對錶現有一些微妙但是重要的影響。
儘管dns.lookup()和各種dns.resolve *()/ dns.reverse()函式有相同的目標將網路的名字與網路地址聯絡在一起(反之亦然),
他們的行為是完全不同的。 這些差異可以有微妙但重大影響著Node.js程式行為。
demo:
const dns = require('dns'); const options = { family: 6,hints: dns.ADDRCONFIG | dns.V4MAPPED,}; dns.lookup('nodejs.cn',options,family) => console.log('address: %j family: IPv%s',family)); // address: "::ffff:112.124.39.54" family: IPv6 options.all = true; dns.lookup('nodejs.cn',addresses) => console.log('addresses: %j',addresses)); // addresses: [{"address":"::ffff:112.124.39.54","family":6}]
dns.lookupService(address,port,callback)
說明:
將引數address和port傳入作業系統底層getnameinfo服務來解析處理並返回主機名。
如果address不是有效的IP地址,會丟擲TypeError。port必須是一個整數.如果不是規定的埠號,會丟擲TypeError.
出錯情況下,err是一個Error物件,err.code程式碼錯誤碼。
demo:
const dns = require('dns'); dns.lookupService('127.0.0.1',22,hostname,service) => { console.log(hostname,service); // localhost ssh });
dns.reverse(ip,callback)
說明:
執行一個反向DNS查詢返回IPv4或IPv6地址的主機名的陣列。
demo:
const dns = require('dns'); dns.reverse('101.20.17.16',hostname) => { console.log(hostname); });
dns.Resolver 類
說明:
DNS請求的獨立解析程式。
使用預設的設定建立一個新的解析程式。
為一個解析程式設定servers使用resolver.setServers(),它不會影響其他的解析程式:
demo:
const { Resolver } = require('dns'); const resolver = new Resolver(); resolver.setServers(['4.4.4.4']); resolver.resolve4('baidu.com',addresses) => { console.log(addresses); });
resolver.cancel()
說明:
取消這個解析程式的未解決的DNS查詢,相應的回撥用一個ECANCELLED碼呼叫。
demo:
const { Resolver } = require('dns'); const resolver = new Resolver(); resolver.setServers(['4.4.4.4']); resolver.resolve4('baidu.com',addresses) => { console.log(addresses); }); resolver.cancel();
dns.resolve(hostname[,rrtype],callback)
說明:
hostname:解析的主機名。
rrtype:資源記錄型別. 預設: ‘A'.c
使用DNS協議來解析一個主機名(e.g. ‘nodejs.org')為一個資源記錄的陣列。
回撥函式的引數為(err,records)。當成功時,records將是一個資源記錄的陣列。它的型別和結構取決於rrtype。
下面是不同rrtype對應resolve的快捷方法:
demo:
const dns = require('dns'); dns.resolve('archive.org','A',addresses) => { if (err) throw err; console.log(`IP 地址: ${JSON.stringify(addresses)}`); }); // IP 地址: ["207.241.224.2"]
dns.resolve4(hostname[,callback)
說明:
使用DNS協議解析IPv4地址主機名(A記錄)。
adresses引數是傳遞給callback函式的IPv4地址陣列。(例如:[‘74.125.79.104',‘74.125.79.105',‘74.125.79.106'])
hostname:需要解析的主機名
options.ttl:記錄每一條記錄的存活次數 (TTL)。如果為 true, 返回的結果將會為 Object 的陣列,就像 { address: ‘1.2.3.4',ttl: 60 } 帶有 TTL 秒數的記錄,而不是 string 的陣列.
demo:
const dns = require('dns'); dns.resolve4('archive.org',{ttl: true},addresses) => { if (err) throw err; console.log(`IPv4地址陣列: ${JSON.stringify(addresses)}`); }); // IPv4地址陣列: [{"address":"207.241.224.2","ttl":58}]
dns.resolve6(hostname[,callback)
說明:
使用DNS協議解析IPv6地址主機名(AAAA記錄)。
adresses引數是傳遞給callback函式的IPv6地址陣列.
demo:
const dns = require('dns'); dns.resolve6('www.taobao.com',addresses) => { if (err) throw err; console.log(`IPv6地址主機名: ${JSON.stringify(addresses)}`); }); // IPv6地址主機名: []
dns.resolveCname(hostname,callback)
說明:
使用DNS協議解析CNAME記錄主機名。
adresses引數是傳遞給callback函式規範內有效的主機名陣列(例如:[‘bar.example.com']).
demo:
const dns = require('dns'); dns.resolveCname('www.taobao.com',addresses) => { if (err) throw err; console.log(`CNAME記錄主機名: ${JSON.stringify(addresses)}`); }); // CNAME記錄主機名: ["www.taobao.com.danuoyi.tbcache.com"]
dns.resolveMx(hostname,callback)
說明:
使用DNS協議處理郵件交換記錄主機名(MX記錄)。
adresses引數是傳遞給callback函式的主機名物件陣列,對
象包含priority和exchange屬性(例如: [{priority: 10,exchange: ‘mx.example.com'},…])。
demo:
const dns = require('dns'); dns.resolveMx('mail.qq.com',addresses) => { if (err) throw err; console.log(`MX記錄: ${JSON.stringify(addresses)}`); });
dns.resolveNaptr(hostname,callback)
說明:
使用DNS協議來處理基於正則表示式匹配的記錄(NAPTR記錄)的主機名。
adresses引數是傳遞給callback函式的主機名物件陣列,物件包含屬性:
flags
service
regexp
replacement
order
preference
demo:
const dns = require('dns'); dns.resolveNaptr('www.taobao.com',addresses) => { if (err) throw err; console.log(`NAPTR記錄: ${JSON.stringify(addresses)}`); });
dns.resolveNs(hostname,callback)
說明:
使用DNS協議處理名稱伺服器主機名記錄(NS記錄)。
adresses為有效的名稱伺服器記錄主機名陣列(eg:[‘ns1.example.com',‘ns2.example.com'])。
demo:
const dns = require('dns'); dns.resolveNs('www.taobao.com',addresses) => { if (err) throw err; console.log(`NS記錄: ${JSON.stringify(addresses)}`); });
dns.resolvePtr(hostname,callback)
說明:
使用DNS協議處理主機名引用記錄(PTR記錄)。
addresses引數將一個字串陣列傳遞給回撥函式callback,其中包含回覆記錄。
demo:
const dns = require('dns'); dns.resolvePtr('www.taobao.com',addresses) => { if (err) throw err; console.log(`PTR記錄: ${JSON.stringify(addresses)}`); });
dns.resolveSoa(hostname,callback)
說明:
使用DNS協議處理主機名子域名記錄(SOA記錄)。addresses引數為一個物件包含以下屬性:
nsname
hostmaster
serial
refresh
retry
expire
minttl
demo:
const dns = require('dns'); dns.resolveSoa('www.taobao.com',addresses) => { if (err) throw err; console.log(`SOA記錄: ${JSON.stringify(addresses)}`); });
dns.resolveSrv(hostname,callback)
說明:
使用DNS協議來處理主機名服務記錄(SRV記錄)。
callback函式返回的addresses引數為物件陣列,每個物件包含以下屬性:
priority
weight
port
name
demo:
const dns = require('dns'); dns.resolveSrv('www.taobao.com',addresses) => { if (err) throw err; console.log(`SRV記錄: ${JSON.stringify(addresses)}`); });
dns.resolveTxt(hostname,callback)
說明:
使用DNS協議處理文字查詢主機名(TXT記錄)。回撥函式callback會返回records引數,
它是一個文字記錄與主機名一一對應的二維陣列(例如:[ [‘v=spf1 ip4:0.0.0.0 ‘,‘~all' ] ]).
每個陣列文字塊包含一條記錄。根據用例,這些可以是連線在一起或單獨對待。
demo:
const dns = require('dns'); dns.resolveTxt('www.taobao.com',addresses) => { if (err) throw err; console.log(`TXT記錄: ${JSON.stringify(addresses)}`); });
dns.resolveAny(hostname,callback)
說明:
使用DNS協議解析所有記錄。
callback函式的引數將是一個包含各種型別記錄的陣列。每個物件都有一個屬性type,指示當前記錄的型別。
“A”、”AAAA”、”CNAME”、”MX”、”NAPTR”、”NS”、”PTR”、”SOA”、”SRV”、”TXT”等
demo:
const dns = require('dns'); dns.resolveAny('www.taobao.com',addresses) => { if (err) throw err; console.log(`${JSON.stringify(addresses)}`); }); // [ { type: 'A',address: '127.0.0.1',ttl: 299 },// { type: 'CNAME',value: 'example.com' },// { type: 'MX',exchange: 'alt4.aspmx.l.example.com',priority: 50 },// { type: 'NS',value: 'ns1.example.com' },// { type: 'TXT',entries: [ 'v=spf1 include:_spf.example.com ~all' ] },// { type: 'SOA',// nsname: 'ns1.example.com',// hostmaster: 'admin.example.com',// serial: 156696742,// refresh: 900,// retry: 900,// expire: 1800,// minttl: 60 } ]
錯誤碼
說明:
每個DNS查詢可以返回一個錯誤程式碼如下:
dns.NODATA:DNS服務返回沒有資料。
dns.FORMERR:DNS伺服器查詢沒有格式化。
dns.SERVFAIL:DNS伺服器返回失敗。
dns.NOTFOUND:域名未找到。
dns.NOIMP: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請求庫初始化未完成。
dns.LOADIPHLPAPI:載入iphlpapi.dll(Windows IP輔助API應用程式介面模組)錯誤
dns.ADDRGETNETWORKPARAMS:找不到GetNetworkParams(讀取本機DNS資訊)函式
dns.CANCELLED:DNS查詢取消
dns.lookup() 與 dns.resolve(),dns.resolve*() and dns.reverse()
說明:
在底層,dns.lookup()使用作業系統設施與大多數其他程式相同。
例如,dns.lookup()幾乎總是解析給定的主機名與ping命令一樣。
在許多類POSIX作業系統中, dns.lookup()函式的行為可以通過改變nsswitch.conf(5)並且/或resolv.conf(5)設定進行改變,
但是需要注意改變這些檔案就意味著改變所有正在這個作業系統中執行 的所有程序的行為。
儘管以非同步JavaScript的角度來呼叫dns.lookup(),但在內部libuv底層執行緒池中卻是同步的呼叫getaddrinfo(3)
dns.resolve(),dns.resolve*() and dns.reverse()這些功能實現與dns.lookup()截然不同。
它們不僅沒有使用getaddrinfo(3)並且通過網路執行DNS查詢。使用非同步網路通訊,並且沒有使用libuv執行緒池。
因此,這些函式不會像使用libuv執行緒池的dns.lookup()函式一樣會對其它程序有負面影響。
它們不像dns.lookup()一樣使用相同的配置檔案。例如,它們不會使用來自/etc/hosts配置。
希望本文所述對大家node.js程式設計有所幫助。