開始這個實例之前,我們簡單談一下Node.js吧,Node.js是一個由JavaScript書寫而成的強大Web開發框架,它讓開發強壯的、伸縮性良好的伺服器端Web應用變得更加簡單、容易。這種技術誕生於09年末,在一個JavaScript大會上宣佈,當時這項在伺服器端運行JavaScript技術讓所 ...
開始這個實例之前,我們簡單談一下Node.js吧,Node.js是一個由JavaScript書寫而成的強大Web開發框架,它讓開發強壯的、伸縮性良好的伺服器端Web應用變得更加簡單、容易。這種技術誕生於09年末,在一個JavaScript大會上宣佈,當時這項在伺服器端運行JavaScript技術讓所有參會者驚奇,當時這位提出者給出了一個“hello world”的程式。
1 var http = require('http');
2 var server = http.createServer(function(req,res){
3 res.writeHead(200);
4 res.end('Hello World');
5 });
6 server.listen(3000,'127.0.0.1');
7 console.log("please run at 127.0.0.1:3000");
於是在地址欄輸入127.0.0.1:3000後就出現了我們非常熟悉的“Hello World”
好,簡單介紹下Node.js,接下來就開始我們的正題,簡單搭建一個DNS查詢工具
準備前期:確保已經安裝Node.js,網路上面有很多安裝教程,在這裡就不詳細多說了
(1)需要載入的Node.js原生模塊:
- Node.js的HTTP模塊,用於創建Web的HTTP伺服器
- Node.js的dns模塊,用於DNS功能變數名稱解析
- Node.js的fileSystem模塊,用於讀取HTML頁面
- Node.js的querystring模塊,處理請求參數
1 var http = require('http'),
2 dns = require('dns'),
3 fs = require('fs');
4 url = require('url');//處理文件url路徑
5 querystring = require('querystring');//處理前端傳回的字元串解析
(2)添加HTTP伺服器代碼,返回顯示index.html(PS:如果是返回html數據,則Content-Type類型值為text/html)
1 http.createServer(function(req,res){
2 var pathname = url.parse(req.url).pathname;
3 req.setEncoding("utf8");
4 res.writeHead(200,{'Content-Type':'text/html'});
5 router(res,req,pathname);
6 }).listen(3000,'127.0.0.1'); //監聽地址為127.0.0.1:3000
7 console.log("You can try it at 127.0.0.1:3000");
解析出請求中的地址後,用一個路由處理器判斷區分用戶是要顯示index.html主頁,還是要進行/parse解析操作,這裡的路由控制器就是router方法
(3)處理url路由
1 function router(res,req,pathname){
2 switch(pathname){
3 case "/parse":parseDns(res,req);break; //解析url地址
4 default:goIndex(res,req); //顯示index主頁
5 }
6 }
- goIndex(res,req)函數,主要用於顯示一個index.html頁面,參數:res 為響應客戶端請求對象;req 為客戶端請求對象
1 function goIndex(res,req){
2 var readPath = __dirname + '/' + url.parse('index.html').pathname;
3 var indexPage = fs.readFileSync(readPath);//讀取html數據,存放在indexpage變數之中
4 res.end(indexPage); //響應html數據到客戶端
5 }
- parseDns(res,req)函數,主要用於解析客戶端傳遞來的功能變數名稱,並且返回該功能變數名稱對應的IP地址
1 1 function parseDns(res,req){
2 2 var postData = "";
3 3 req.addListener("data",function(postDataChunk){
4 4 postData += postDataChunk;
5 5 });
6 6 req.addListener("end",function(){
7 7 var resData = getDns(postData,function(domain,addresses){
8 8 res.writeHead(200,{'Content-Type':'text/html'});
9 9 res.end("</html><head><meta http-equiv='content-type' content='text/html;charset=utf-8'></head><body><div style='text-align:center'>Domain:<span style='color:red'>" + domain + "</span><br/>IP:<span style='color:red'>" + addresses.join(',') + "</span></div></body></html>");
10 10 return;
11 11 })
12 12 })
13 13 }
14 14
15 15 function getDns(postData,callback){
16 16 var domain = querystring.parse(postData).search_dns;
17 17 console.log(postData); //search_dns=www.qq.com
18 18 console.log(querystring.parse(postData));//{ search_dns: 'www.qq.com' }
19 19 console.log(domain); //www.qq.com/
20 20 dns.resolve(domain,function(err,addresses){ //返回的addresses是一個數組
21 21 if(!addresses){
22 22 addresses=['不存在功能變數名稱'];
23 23 }
24 24 callback(domain,addresses);
25 25 })
26 26 }
註意:由於dns.resolve()方法是一個非同步執行函數,如果想使用它執行的結果,需要有一個回調函數,並把結果作為參數傳入回調函數,才可以傳遞到函數外面!
(4)主頁index.html代碼
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>DNS查詢</title>
5 <meta http-equiv="content-type" content="text/html;charset=utf-8">
6 </head>
7 <body>
8 <h1 style='text-align:center'>DNS查詢工具</h1>
9 <div style='text-align:center'>
10 <form action="/parse" method="post">
11 查詢DNS:<input type='text' name='search_dns'/>
12 <input type='submit' value='查詢'/>
13 </form>
14 </div>
15 </body>
到了這裡,已經實現了DNS查詢功能了,我把(1)(2)(3)(4)步的代碼都放在一個叫parse_dns.js的文件夾裡面,在同一根目錄文件下存放(5)步的index.html,然後再命令行視窗下找到當前目錄(一開始我是用很笨的方法用cd命令找到文件根目錄,後來發現sublimeText的Side Bar插件可以直接在所選文件夾右鍵點擊“Open/Run”,直接打開一個叫Window PowerShell的藍色視窗,功能和cmd視窗一樣,在那裡已經幫你自動找好文件路徑,非常方便),然後直接輸入node parse_dns.js,即可顯示"You can try it at 127.0.0.1:3000"
在瀏覽器地址欄輸入“127.0.0.1:3000”,就有下圖界面
輸入“www.baidu.com”進行查詢,頁面就跳到了“127.0.0.1:3000/parse”
進行到這一步已經是基本完成了,但是筆者並沒有將這個系統進行模塊化,比如分成伺服器創建模塊、路由處理模塊、邏輯控制模塊、錯誤處理模塊等,要想讓程式更加健壯並且項目可維護性高,這個是必不可少的,由於是剛學node不久,日後必定寫上更好的版本。
思考:
(1)這個小工具還存在一些小問題,就是如果我輸入類似“https://www.baidu.com/”這樣子的格式,程式會解析不成功,而返回“功能變數名稱不存在”,所以日後我需要引入Node.js的原生模塊url,用於url的分解
(2)筆者輸入“www.qq.com”解析出來的IP,放在瀏覽器地址欄里打開但並不是騰訊的主頁,然而輸入“www.baidu.com”解析出來的IP卻可以呈現度娘的搜索首頁,筆者的室友說是因為有多個伺服器解析出來的多個IP,所以這個IP可能不是我正在看到的騰訊主頁,還有一個解釋是因為埠問題,百度搜索首頁是預設80埠,而騰訊首頁不是,所以要知道埠號並加到IP後面才可以訪問,問題還沒搞清楚,所以筆者還會繼續研究~