zoukankan      html  css  js  c++  java
  • Node.js:DNS模块的使用

    Nodejs的DNS模块包涵有关DNS查询和操作的方法,下面介绍该模块的基本用法以及实现一个DNS查询小工具。

    1.获取DNS服务器地址

    使用getServers方法,该方法返回一个IP地址组成的数组,如下所示:

    const dns = require('dns');
    const servers = dns.getServers();
    console.log(servers);
    

    返回结果为:

    [ '114.114.114.114', '8.8.8.8',
    'fec0:0:0:ffff::1', '114.114.114.114',
    '8.8.8.8', '114.114.114.114',
    '8.8.8.8' ]

    2.使用系统特性域名解析获取IP地址

    使用dns.lookup(hostname[, options], callback)方法,options参数包涵以下属性:

    • family:地址协议族,必须为4或6的整数
    • hints:设置getaddrinfo的标志,dns.ADDRCONFIG 或者 dns.V4MAPPED(ipv4映射成ipv6)
    • all:false(默认),布尔值,如设置为true,则返回IP数组,否则返回单个IP地址

    callback回调函数有三个参数(err,address,family),如果options的all属性设置为true,则只有(err,addresses)参数且addresses为一个数组,数组元素为{address,family}对象。使用如下所示:

    dns.lookup('www.baidu.com',(err,address,family)=>{
    	if(err) throw err;
    	console.log('百度网站的IP地址是:'+address+'地址协议族是:IPV'+family);
    });
    

    结果如下:

    E:developmentdocument odejsdemo>node dns-example.js
    百度网站的IP地址是:14.215.177.37地址协议族是:IPV4

    设置options的all为true时,结果如下:

    dns.lookup('www.baidu.com',{family:4,all:!0,hints:dns.ADDRCONFIG|dns.V4MAPPED},(err,addresses)=>{
    	if(err) throw err;
    	addresses.forEach((ele,idx,arr)=>{
    		console.log('百度网站的IP地址'+(idx+1)+'是:'+ele.address);
    	});
    });
    

    结果如下:

    E:developmentdocument odejsdemo>node dns-example.js
    百度网站的IP地址1是:14.215.177.38
    百度网站的IP地址2是:14.215.177.37

    3.根据IP和端口获取主机名

    使用dns.lookupService(address, port, callback)方法,该方法依赖getnameinfo底层函数。
    callback函数有三个参数(err, hostname, service),service是protocol,为http或https,使用如下所示:

    dns.lookupService('127.0.0.1',80,(err,hostname,service)=>{
    	if(err) console.log(err);
    	console.log('该IP对应的主机为:'+hostname+' 协议为:'+service);
    });
    

    结果如下:

    E:developmentdocument odejsdemo>node dns-example.js
    该IP对应的主机为:www.test.zmx.com 协议为:http

    4.使用网络域名解析获取IP地址

    使用dns.resolve(hostname[, rrtype], callback)方法,rrtype有以下选择:

    • 'A':IPV4,default
    • 'AAAA':IPV6
    • 'MX' - mail exchange records 邮件交换记录
    • 'TXT' - text records 域名配置说明
    • 'SRV' - SRV records 服务器提供的服务
    • 'PTR' - PTR records
    • 'NS' - name server records 域名服务器
    • 'CNAME' - canonical name records 别名记录
    • 'SOA' - start of authority record 起始授权机构
    • 'NAPTR' - name authority pointer record

    callback函数有(err, addresses)两个参数,addresses是一个数组,具体成员需要看具体的rrtype,使用如下所示:

    //获取IPV4
    dns.resolve('www.qq.com','A',(err,address)=>{
    	if(err) throw err;
    	console.log(address);//结果为[ '14.17.32.211', '14.17.42.40', '59.37.96.63' ]
    });
    //获取IPV6
    dns.resolve('www.qq.com','AAAA',(err,address)=>{
    	if(err) throw err;
    	console.log(address);//结果为[ '240e:ff:f040:28::a' ]
    });
    //获取SOA信息
    dns.resolve('www.qq.com','SOA',(err,address)=>{
    	if(err) throw err;
    	console.log(address);
    	//结果为
    	{ nsname: 'ns-tel1.qq.com',
          hostmaster: 'webmaster.qq.com',
          serial: 1380440321,
          refresh: 300,
          retry: 600,
          expire: 86400,
          minttl: 300 }
    });
    //获取别名CNAME
    dns.resolve('www.baidu.com','CNAME',(err,address)=>{
    	if(err) throw err;
    	console.log(address);//结果为[ 'www.a.shifen.com' ]
    });
    

    resovle还存在很多快捷方法,例如:resolve4,resolve6,resolveCname...等等

    5.反向域名解析

    使用dns.reverse(ip, callback)方法,callback有两个参数(err, hostnames),hostnames是一个域名数组,使用如下所示:

    dns.reverse('114.114.114.114',(err,hostnames)=>{
    	if(err) throw err;
    	console.log(hostnames);//结果为[ 'public1.114dns.com' ]
    });
    

    学完了以上的知识后,可以做个DNS查询的小工具,如下所示:
    第一步,写个HTML静态页面,如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>DNS查询工具</title>
    	<style type="text/css">
    		html,body{  100%; height: 100%; }
    		body{ display: flex; align-items: center; justify-content: center; flex-direction: column; }
    		*{ margin:0; padding: 0; }
    		ul{ list-style: none; }
    		.res{line-height: 24px; color:#333; }
    		.clearfix:after{ display: block; content:''; height: 0; visibility: hidden; clear: both;}
    		.fl{ float:left; }
    		.g-wrap{  display: flex;  560px;  height: 40px; }
    		.u-list{position: relative; flex:1;  }
    		.u-inp{flex:3; border:1px solid #ccc; border-left: none; border-right:none; padding:11px 0 11px 10px;}
    		.u-btn{ flex:1; }
    		.list{ display: none; position: absolute; left: 0px; top:40px;  100%; border:1px solid #ccc; border-top:none; border-bottom:none; box-sizing: content-box; }
    		.item{ height: 30px; line-height: 30px; text-align: center; color: #666; border-bottom: 1px solid #ccc; cursor:pointer;}
    		.item:hover{ color:#0087dc; }
    		.u-list .type{ display: block;   100%;  line-height: 38px; border:1px solid #ccc;  text-align: center; color:#666; text-decoration: none; }
    		.u-list .type:after{ content: ''; position: absolute; 0; height:0; border:8px solid transparent; border-top-color:#ccc; right:4px; top:16px;}
    		.u-inp input{  100%; border:none; outline: none; height: 18px; line-height: 18px; color:#666; vertical-align: top; font-size: 14px; }
    		.u-btn .btn{ display: block; line-height: 40px; text-align: center; background-color: #0087dc; color:#fff; font-size: 16px; cursor:pointer; transition: background-color .3s;}
    		.u-btn .btn:hover{ background-color: #0060b2; }
    	</style>
    </head>
    <body>
    	<div id="res" class="res"></div>
    	<div class="g-wrap clearfix">
    		<div class="u-list fl">
    			<a href="javascript:;" class="type" id="type" data-value="A">IPV4</a>
    			<ul id="list" class="list">
    				<li class="item" data-value="A">IPV4</li>
    				<li class="item" data-value="AAAA">IPV6</li>
    				<li class="item" data-value="CNAME">CNAME</li>
    				<li class="item" data-value="SOA">SOA</li>
    			</ul>
    		</div>
    		<div class="u-inp fl">
    			<input type="text" class="host" id="host" placeholder="请输入域名">
    		</div>
    		<div class="u-btn fl">
    			<span class="btn" id="btn">查询</span>
    		</div>
    	</div>
    	<script>
    		function hide(el){
    			el.style.display = 'none';
    		}
    		function show(el){
    			el.style.display = 'block';
    		}
    		function dealResult(responseText){
    			var ips = [],
    				result = '';
    			ips = JSON.parse(responseText).ips;
    			if(Array.isArray(ips)){
    				result = ips.length > 0 ? ips.join('<br />') : '没有查询到结果';
    			}else if({}.toString.call(ips) === '[object Object]'){
    				result = JSON.stringify(ips);
    			}
    			res.innerHTML = result;
    		}
    		type.addEventListener('click',function(e){
    			e.stopPropagation();
    			show(list);
    		},!1);
    		[].slice.call(document.body.querySelectorAll('.item')).forEach(function(el,idx,arr){
    			el.addEventListener('click',function(e){
    				type.innerText = this.innerText;
    				type.dataset.value = this.dataset.value;
    			},!1);
    		});
    		document.body.addEventListener('click',function(e){
    			if(list.style.display === 'block'){ hide(list); }
    		},!1);
    		btn.addEventListener('click',function(e){
    			var hostname = host.value.trim(),
    				rrtype   = type.dataset.value.toUpperCase();
    			if(hostname == '') return;
    			if(hostname.indexOf('http://') === 0) hostname = hostname.replace('http://','');
    			var xhr = new XMLHttpRequest(),
    				method = "POST",
    				url = "/dnslookup";
    
    			xhr.open(method, url, true);
    			xhr.onreadystatechange = function() {
    				if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
    					dealResult(xhr.responseText);
    				}
    			};
    			xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    			xhr.send('host='+hostname+'&rrtype='+rrtype);
    		},!1);
    	</script>
    </body>
    </html>
    

    接着编写服务端代码,如下:

    var http = require('http'),
    	url  = require('url'),
    	dns  = require('dns'),
    	qs   = require('querystring'),
    	fs   = require('fs');
    
    function router(req,res,pathname){
    	switch(pathname){
    		case '/dnslookup':
    			lookup(req,res);
    			break;
    		default:
    			showIndex(req,res);
    	}
    }
    
    function showIndex(req,res){
    	var pagePath = __dirname+'/'+'dns-lookup.html';
    	var html = fs.readFileSync(pagePath);
    	res.end(html);
    }
    
    function lookup(req,res){
    	var postData = '';
    	req.on('data',function(data){
    		postData+=data;
    	});
    	req.on('end',function(data){
    		var json = qs.parse(postData);
    		var hostname = json.host;
    		var rrtype = json.rrtype;
    		dns.resolve(hostname,rrtype,function(err,adresses){
    			if(err){
    				res.end(JSON.stringify({errcode:1,ips:[]}));
    			}
    			res.end(JSON.stringify({errcode:0,ips:adresses}));
    		});
    		
    	});
    }
    
    http.createServer(function(req,res){
        var pathname = url.parse(req.url).pathname;
        req.setEncoding("utf8");
        res.writeHead(200,{'Content-Type':'text/html'});
        router(req,res,pathname);
    }).listen(3000,'127.0.0.1');
    

    运行效果如下:

    到此这个小工具便完成了。

  • 相关阅读:
    c++中的内存管理【转载】
    c++中dynamic_cast、static_cast、reinterpret_cast和const_cast作用
    c++中的顶层const和底层const
    c++赋值操作符需要确保自我赋值的安全性问题
    二分法查找
    Servlet基础总结
    java 正则表达式:有丶东西
    HTTP协议初步认识
    Java synchronized到底锁住的是什么?
    ECMA Script 6新特性之解构赋值
  • 原文地址:https://www.cnblogs.com/zmxmumu/p/6089025.html
Copyright © 2011-2022 走看看