浅析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 相关文章推荐
详解JavaScript函数绑定
Aug 18 Javascript
JQuery文字列表向上滚动的代码
Nov 13 Javascript
jqueryUI里拖拽排序示例分析
Feb 26 Javascript
javascript实现英文首字母大写
Apr 23 Javascript
基于JQuery实现仿网易邮箱全屏动感滚动插件fullPage
Sep 20 Javascript
Jquery Ajax Error 调试错误的技巧
Nov 20 Javascript
jquery属性,遍历,HTML操作方法详解
Sep 17 Javascript
使用JSON作为函数的参数的优缺点
Oct 27 Javascript
AngularJs基于角色的前端访问控制的实现
Nov 07 Javascript
JavaScript比较同一天的时间大小实例代码
Feb 09 Javascript
jQuery滚动条美化插件nicescroll简单用法示例
Apr 18 jQuery
3分钟读懂移动端rem使用方法(推荐)
May 06 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
jquery 读取页面load get post ajax 四种方式代码写法
2011/04/02 Javascript
js数组的操作详解
2013/03/27 Javascript
iframe窗口高度自适应的实现方法
2014/01/08 Javascript
浅谈JS闭包中的循环绑定处理程序
2014/11/09 Javascript
使用bootstrap3开发响应式网站
2016/05/12 Javascript
ionic 上拉菜单(ActionSheet)实例代码
2016/06/06 Javascript
jQuery操作iframe中js函数的方法小结
2016/07/06 Javascript
JavaScript面试开发常用的知识点总结
2016/08/08 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
2016/08/26 Javascript
JS变量及其作用域
2017/03/29 Javascript
老生常谈Bootstrap媒体对象
2017/07/06 Javascript
基于bootstrap实现多个下拉框同时搜索功能
2017/07/19 Javascript
解决vue中使用Axios调用接口时出现的ie数据处理问题
2018/08/13 Javascript
在js代码拼接dom对象到页面上的模板总结
2018/10/21 Javascript
微信小程序实现搜索功能并跳转搜索结果页面
2019/05/18 Javascript
vue项目中使用AES实现密码加密解密(ECB和CBC两种模式)
2019/08/12 Javascript
JS实现骰子3D旋转效果
2019/10/24 Javascript
python实现汉诺塔递归算法经典案例
2021/03/01 Python
对numpy中布尔型数组的处理方法详解
2018/04/17 Python
win7下python3.6安装配置方法图文教程
2018/07/31 Python
对pytorch中的梯度更新方法详解
2019/08/20 Python
python3 selenium自动化 frame表单嵌套的切换方法
2019/08/23 Python
浅析Python+OpenCV使用摄像头追踪人脸面部血液变化实现脉搏评估
2019/10/17 Python
python代码打印100-999之间的回文数示例
2019/11/24 Python
Python如何使用字符打印照片
2020/01/03 Python
微软美国官方网站:Microsoft美国
2018/05/10 全球购物
同志主要表现材料
2014/08/21 职场文书
机关副主任个人四风问题整改措施
2014/09/26 职场文书
企业与个人合作经营协议书
2014/11/01 职场文书
新年晚会主持词开场白
2015/05/28 职场文书
Python趣味挑战之用pygame实现简单的金币旋转效果
2021/05/31 Python
教你如何让spark sql写mysql的时候支持update操作
2022/02/15 MySQL
Python GUI编程之tkinter 关于 ttkbootstrap 的使用详解
2022/03/03 Python
面试中老生常谈的MySQL问答集锦夯实基础
2022/03/13 MySQL
vue使用element-ui按需引入
2022/05/20 Vue.js
js前端面试常见浏览器缓存强缓存及协商缓存实例
2022/06/21 Javascript