NodeJs 入門到放棄 — 網絡服務器(三)
碼文不易啊,轉載請帶上本文鏈接呀,感謝感謝 //www.cnblogs.com/echoyya/p/14484454.html
http (協議)
網絡是信息傳輸、接收、共享的虛擬平台,而網絡傳輸數據有一定的規則,稱協議,而HTTP協議就是其中之一,且使用最為頻繁。
定義、約束、交互特點、工作原理
定義:HTTP 即 超文本傳輸協議
,是一種網絡傳輸協議,採用的是請求 / 響應
方式傳遞數據,該協議規定了數據在服務器與瀏覽器之間,傳輸數據的格式與過程
約束:
-
約束了瀏覽器以何種格式兩服務器發送數據
-
約束了服務器以何種格式接收客戶端發送的數據
-
約束了服務器以何種格式響應數據給瀏覽器
-
約束了以何種格式接收服務器響應的數據
交互特點:
- HTTP是無連接:無連接的含義是一次請求對應一次響應,限制每次連接只處理一個請求。服務器處理完客戶端的請求,並收到客戶端的應答後,即斷開連接。採用這種方式可以節省傳輸時間。
- 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')) })
作為服務器處理響應
實現一個簡易服務器步驟:
-
引入http通訊模塊
-
創建服務器對象
-
監聽 request 事件接收客戶端請求
-
監聽端口實現服務器功能
-
訪問瀏覽器 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....');
})
客戶端向服務器端傳遞數據
-
GET 方式
:GET請求直接被嵌入在路徑中,URL是完整的請求路徑,包括了?後面的部分,可以解析後面的內容作為GET請求的參數。且url 模塊中的 parse 函數提供了這個功能。
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);
-
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)
}