NodeJs 入門到放棄 — 網絡服務器(三)

碼文不易啊,轉載請帶上本文鏈接呀,感謝感謝 //www.cnblogs.com/echoyya/p/14484454.html

http (協議)

網絡是信息傳輸、接收、共享的虛擬平台,而網絡傳輸數據有一定的規則,稱協議,而HTTP協議就是其中之一,且使用最為頻繁。

定義、約束、交互特點、工作原理

定義:HTTP 即 超文本傳輸協議,是一種網絡傳輸協議,採用的是請求 / 響應方式傳遞數據,該協議規定了數據在服務器與瀏覽器之間,傳輸數據的格式與過程

約束:

  1. 約束了瀏覽器以何種格式兩服務器發送數據

  2. 約束了服務器以何種格式接收客戶端發送的數據

  3. 約束了服務器以何種格式響應數據給瀏覽器

  4. 約束了以何種格式接收服務器響應的數據

交互特點:

  1. HTTP是無連接:無連接的含義是一次請求對應一次響應,限制每次連接只處理一個請求。服務器處理完客戶端的請求,並收到客戶端的應答後,即斷開連接。採用這種方式可以節省傳輸時間。
  2. HTTP是媒體獨立的:只要客戶端和服務器知道如何處理的數據內容,任何類型的數據都可以通過HTTP發送。客戶端以及服務器指定使用適合的MIME-type類型。

工作原理:

在瀏覽器地址欄中輸入網址,將網址發送DNS服務器進行域名解析,獲取對應的IP地址,3次握手,瀏覽器與目標服務器建立TCP連接並發起請求,服務器處理請求發出響應,瀏覽器解析htm代碼,對頁面進行渲染呈現給用戶。

上述內容也是一道常見的面試題:瀏覽器輸入地址後發生了什麼

狀態碼

向服務器發出請求,此網頁所在的服務器會返回一個HTTP狀態碼,用以響應瀏覽器的請求。

常見的狀態碼:

  • 200 – 請求成功
  • 301 – 資源被永久轉移到其它URL
  • 404 – 請求的資源不存在
  • 500 – 內部服務器錯誤

MIME 類型

文件類型的一種表述,用於標識文件類型。

常見MIME類型:

  • text/html : .html
  • text/plain :純文本
  • text/xml : xml
  • image/gif :.gif
  • image/jpeg :.jpg
  • image/png:.png

http (模塊)

http模塊是nodejs中系統模塊,用於網絡通訊,可以作為客戶端發送請求,亦可以作為服務器端處理響應

作為客戶端發送請求

由於大多數請求都是不帶請求體的 GET 請求,因此最最最常用的方法:

  • http.get(url[, options][, callback])

    var http = require('http')
    var fs = require('fs')
    
    http.get('//www.baidu.com/',function(res){
      // console.log(res);   
      // res 返回的即為一個可讀流, 
      res.pipe(fs.createWriteStream('./a.html'))
    })
    

作為服務器處理響應

實現一個簡易服務器步驟:

  1. 引入http通訊模塊

  2. 創建服務器對象

  3. 監聽 request 事件接收客戶端請求

  4. 監聽端口實現服務器功能

  5. 訪問瀏覽器 127.0.0.1 或 localhost 或 局域網IP

var http = require('http')

// 創建服務器
var server = http.createServer()

// 監聽request事件,請求發生返回數據,請求一次執行一次
server.on('request',function(req,res){
  // req:請求對象,包含所有客戶端請求的數據,請求頭,請求體
  // res:響應對象,包含所有服務器響應的數據,響應頭,響應體

  // 設置響應頭 文件類型及字符編碼
  res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'}); 

  res.write('<h1 style="color:red">歡迎訪問 nodejs</h1>')
  res.end()  // 服務器結束響應
})

// 監聽服務器80端口,默認就是80
server.listen('80',function(){
  console.log('Server is running....');
})

客戶端向服務器端傳遞數據

  1. GET 方式:GET請求直接被嵌入在路徑中,URL是完整的請求路徑,包括了?後面的部分,可以解析後面的內容作為GET請求的參數。且url 模塊中的 parse 函數提供了這個功能。

    啟動服務訪問://127.0.0.1:3000/?name=Echoyya&city=BeiJing

var http = require('http');
var url = require('url');
 
http.createServer(function(req, res){
    res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
 
    // 解析 url 參數
    var params = url.parse(req.url, true).query;
    res.write("姓名:" + params.name);
    res.write("城市:" + params.city);
    res.end();

}).listen(3000);

  1. POST 方式:POST 請求的內容全部都在請求體中,http.ServerRequest 並沒有一個屬性為請求體, node.js 默認是不會解析請求體的,需要手動來做。

    啟動服務訪問://127.0.0.1:3000/

var http = require('http');
var querystring = require('querystring');
 
var postHTML = 
  '<html><head><meta charset="utf-8"><title>POST</title></head>' +
  '<body>' +
  '<form method="post">' +
  '姓名: <input name="name"><br>' +
  '城市: <input name="city"><br>' +
  '<input type="submit">' +
  '</form>' +
  '</body></html>';
 
http.createServer(function (req, res) {
  // 定義了一個post變量,用於暫存請求體的信息
  var post = "";
  req.on('data', function (chunk) {
    // 通過req的data事件監聽函數,每當接受到請求體的數據,就累加到 post 變量中
    post += chunk;
  });
  // 觸發end事件,通過querystring.parse將post解析為真正的POST請求格式,然後向客戶端返回。
  req.on('end', function () {
    post = querystring.parse(post);   // 解析參數
    // 設置響應頭部信息及編碼
    res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
 
    if(post.name && post.city) {  // 輸出提交的數據
        res.write("姓名:" + post.name);
        res.write("<br>");
        res.write("城市:" + post.city);
    } else {   // 輸出表單
        res.write(postHTML);
    }
    res.end();
  });
}).listen(3000);

網頁模板

首先區分兩個概念:

靜態網頁:標準的HTML文件,可以包含文本,圖像、聲音、動畫等,沒有後台數據庫、不可交互的網頁。但可以出現各種動態的效果,如GIF動畫、滾動字幕等。靜態網頁相對更新起來比較麻煩。

動態網頁:是指跟靜態網頁相對的一種網頁編程技術。頁面代碼雖然沒有變,但是顯示的內容卻是可以隨着時間、參數、環境或者數據庫操作的結果而發生改變。

動態網頁模板

動態獲取訪問者客戶端的IP,輸出到網頁:

var http = require('http');

http.createServer(function (req, res) {
  var ip = req.socket.remoteAddress;
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write("<h1>你的IP地址是:"+ ip +"</h1>");
  res.end()
}).listen(80);

每個客戶端請求的IP都不一樣,可以使用數據拼接的方式,可以達到動態輸出網頁的效果,但輸出給瀏覽的並非是一個完整的網頁,實際上完整的網頁代碼要多得多。

網頁模板工作原理:把一些靜態固定的內容,存儲為靜態文件,動態內容寫成 模板語法,在使用模板引擎讀取該文件,進行內容替換,最終實現一個動態頁面,以下模擬操作:

index.html:使用模板語法,動態獲取訪問者客戶端的IP

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Home</title>
</head>
<body>
  <h1>你的IP地址是:<%=ip%></h1>
</body>
</html>

template.js:啟動服務訪問://127.0.0.1 或本地局域網IP 或 本地可解析域名地址

var http = require('http');
var fs = require('fs');

http.createServer(function (req, res) {
  
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  
  var ip = req.socket.remoteAddress;
  fs.readFile('./index.html',function(err,chunk){
    res.write( render(chunk.toString(),ip) )
    res.end();
  })

}).listen(80);

// 思想: 定義一個render 函數,用於將數據和html進行整合
function render(htmlStr,data){
   return htmlStr.replace('<%=ip%>',data)
}
Tags: