浅析Node.js:DNS模块的使用


Posted in Javascript onNovember 23, 2016

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\nodejsdemo>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\nodejsdemo>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\nodejsdemo>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{ width: 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; width: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; width: 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; width: 100%; line-height: 38px; border:1px solid #ccc; text-align: center; color:#666; text-decoration: none; }
    .u-list .type:after{ content: ''; position: absolute; width:0; height:0; border:8px solid transparent; border-top-color:#ccc; right:4px; top:16px;}
    .u-inp input{ width: 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');

运行效果如下:浅析Node.js:DNS模块的使用

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery 入门讲解1
Apr 15 Javascript
Prototype Date对象 学习
Jul 12 Javascript
有关于JS辅助函数inherit()的问题
Apr 07 Javascript
js获取客户端网卡的IP地址、MAC地址
Mar 26 Javascript
JavaScript实现将xml转换成html table表格的方法
Apr 17 Javascript
获取阴历(农历)和当前日期的js代码
Feb 15 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
Jul 15 Javascript
webpack使用 babel-loader 转换 ES6代码示例
Aug 21 Javascript
node前端开发模板引擎Jade的入门
May 11 Javascript
解决vue 格式化银行卡(信用卡)每4位一个符号隔断的问题
Sep 14 Javascript
使用wxapp-img-loader自定义组件实现微信小程序图片预加载功能
Oct 18 Javascript
原生javascript单例模式的应用实例分析
Feb 23 Javascript
jquery-mobile基础属性与用法详解
Nov 23 #Javascript
微信小程序 wx.request(接口调用方式)详解及实例
Nov 23 #Javascript
利用jquery获取select下拉框的值
Nov 23 #Javascript
JQuery和PHP结合实现动态进度条上传显示
Nov 23 #Javascript
ionic进入多级目录后隐藏底部导航栏(tabs)的完美解决方案
Nov 23 #Javascript
JQueryEasyUI之DataGrid数据显示
Nov 23 #Javascript
详解获取jq ul第一个li定位的四种解决方案
Nov 23 #Javascript
You might like
mysql5详细安装教程
2007/01/15 PHP
网页上facebook分享功能具体实现
2014/01/26 PHP
PHP实现的多彩标签效果代码分享
2014/08/21 PHP
刷新PHP缓冲区为你的站点加速
2015/10/10 PHP
php+ajax无刷新分页实例详解
2015/12/07 PHP
PHP5.5安装PHPRedis扩展及连接测试方法
2017/01/22 PHP
PHP7.0连接DB操作实例分析【基于mysqli】
2019/09/26 PHP
Yii中特殊行为ActionFilter的使用方法示例
2020/10/18 PHP
农历与西历对照
2006/09/06 Javascript
Js之软键盘实现(js源码)
2007/01/30 Javascript
JavaScript学习心得之概述
2015/01/20 Javascript
轻松实现js弹框显示选项
2016/09/13 Javascript
Angularjs使用过滤器完成排序功能
2017/09/20 Javascript
webpack打包node.js后端项目的方法
2018/03/10 Javascript
微信小程序基于Taro的分享图片功能实践详解
2019/07/12 Javascript
javascript json对象小技巧之键名作为变量用法分析
2019/11/11 Javascript
原生js实现无缝轮播图
2020/01/11 Javascript
jQuery实现简单飞机大战
2020/07/05 jQuery
[01:51]2014DOTA2西雅图邀请赛 MVP 外卡赛black场间采访
2014/07/09 DOTA
[47:12]TFT vs Secret Supermajor小组赛C组 BO3 第三场 6.3
2018/06/04 DOTA
[01:14:41]DOTA2-DPC中国联赛定级赛 iG vs Magma BO3第一场 1月8日
2021/03/11 DOTA
Python实现发送email的几种常用方法
2014/08/18 Python
Python实现字符串格式化输出的方法详解
2017/09/20 Python
python将视频转换为全字符视频
2019/04/26 Python
python Web flask 视图内容和模板实现代码
2019/08/23 Python
python解释器pycharm安装及环境变量配置教程图文详解
2020/02/26 Python
python 按钮点击关闭窗口的实现
2020/03/04 Python
Python unittest如何生成HTMLTestRunner模块
2020/09/08 Python
结合CSS3的新特性来总结垂直居中的实现方法
2016/05/30 HTML / CSS
德国最大的网上足球商店:11teamsports
2019/09/11 全球购物
大学生自我评价怎样写好
2013/10/23 职场文书
出差报告范文
2014/11/06 职场文书
2014年党总支工作总结
2014/12/18 职场文书
2015年学校教务处工作总结
2015/05/11 职场文书
2015年安全生产月工作总结
2015/07/27 职场文书
Kubernetes控制节点的部署
2022/04/01 Servers