浅析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序列化form表单使用ajax提交后处理返回的json数据
Mar 03 Javascript
从零学jquery之如何使用回调函数
May 16 Javascript
Javascript控制div属性动态变化实例分析
Oct 08 Javascript
jQuery中的ready函数与window.onload谁先执行
Jun 21 Javascript
浅谈$('div a') 与$('div&gt;a')的区别
Jul 18 Javascript
实例分析js事件循环机制
Dec 13 Javascript
微信小程序实现随机验证码功能
Dec 20 Javascript
js实现继承的方法及优缺点总结
May 08 Javascript
解决使用layui的时候form表单中的select等不能渲染的问题
Sep 18 Javascript
Vue实现计算器计算效果
Aug 17 Javascript
Vue获取微博授权URL代码实例
Nov 04 Javascript
JavaScript展开运算符和剩余运算符的区别详解
Feb 18 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
PHP获取php,mysql,apche的版本信息示例代码
2014/01/16 PHP
jquery JSON的解析方式
2009/07/25 Javascript
JavaScript 直接操作本地文件的实现代码
2009/12/01 Javascript
跟我学Nodejs(一)--- Node.js简介及安装开发环境
2014/05/20 NodeJs
jquery 为a标签绑定click事件示例代码
2014/06/23 Javascript
浅谈JavaScript数据类型及转换
2015/02/28 Javascript
javascript中in运算符用法分析
2015/04/28 Javascript
js实现文字在按钮上滚动的方法
2015/08/20 Javascript
微信小程序 教程之小程序配置
2016/10/17 Javascript
JS字符串长度判断,超出进行自动截取的实例(支持中文)
2017/03/06 Javascript
深入理解Commonjs规范及Node模块实现
2017/05/17 Javascript
详解JS构造函数中this和return
2017/09/16 Javascript
js中DOM事件绑定分析
2018/03/18 Javascript
浅谈如何使用webpack构建多页面应用
2018/05/30 Javascript
D3.js实现拓扑图的示例代码
2018/06/30 Javascript
vue router导航守卫(router.beforeEach())的使用详解
2019/04/19 Javascript
[04:47]DOTA2-潍坊风行电子俱乐部探秘
2014/08/08 DOTA
[01:05:36]VP vs TNC Supermajor小组赛B组 BO3 第二场 6.2
2018/06/03 DOTA
Python的math模块中的常用数学函数整理
2016/02/04 Python
Windows下anaconda安装第三方包的方法小结(tensorflow、gensim为例)
2018/04/05 Python
从django的中间件直接返回请求的方法
2018/05/30 Python
keras 权重保存和权重载入方式
2020/05/21 Python
Django serializer优化类视图的实现示例
2020/07/16 Python
python实现文件+参数发送request的实例代码
2021/01/05 Python
美国睫毛、眉毛精华液领导品牌:RevitaLash Cosmetics
2018/03/26 全球购物
Under Armour西班牙官网:美国知名的高端功能性运动品牌
2018/12/12 全球购物
大专生的学习自我评价
2013/12/04 职场文书
美德好少年主要事迹
2014/01/29 职场文书
高中军训感言800字
2014/03/05 职场文书
高中生操行评语
2014/04/25 职场文书
文明之星事迹材料
2014/05/09 职场文书
区政府领导班子个人对照检查材料
2014/09/25 职场文书
关于学习的决心书
2015/02/05 职场文书
Vue中foreach数组与js中遍历数组的写法说明
2021/06/05 Vue.js
Python可视化学习之matplotlib内置单颜色
2022/02/24 Python
mybatis-plus模糊查询指定字段
2022/04/28 Java/Android