利用Node能夠十分方便的搭建網絡服務器。算法
Node提供了net、dgram、http、https等4個模塊,分別用於處理TCP、UDP、HTTP、HTTPS,適用於服務器端和客戶端。編程
TCP服務在網絡應用中十分常見,大多數的應用都是基於TCP搭建而成的。瀏覽器
TCP全名爲傳輸控制協議,在OSI模型(物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層)中屬於傳輸層協議。安全
TCP是面向鏈接的協議,其顯著的特徵是傳輸以前須要3次握手造成會話。bash
只有會話造成後,服務器端和客戶端之間才能相互發送數據。在建立會話的過程當中,服務器端和客戶端分別提供一個套接字,這兩個套接字共同造成一個鏈接。服務器端和客戶端則經過套接字實現二者之間的操做。服務器
經過net.createServer(listener)便可建立一個TCP服務器,listener是鏈接事件connection的偵聽器。網絡
能夠利用Telnet工具做爲客戶端對建立的服務器進行會話交流。併發
TCP服務的事件分爲服務器事件和鏈接事件。socket
服務器事件高併發
對於經過net.createServer()建立的服務器而言,它是一個EventEmitter實例,自定義事件有:
鏈接事件
服務器能夠同時與多個客戶端保持鏈接,對於每一個鏈接而言是典型的可寫可讀Stream對象。Stream對象能夠用於服務器端和客戶端之間的通訊,既能夠經過data事件從一端讀取另外一端發來的數據,也能夠經過write()方法從一端向另外一端發送數據。自定義事件:
TCP套接字是可寫可讀的Stream對象,能夠利用pipe()方法巧妙地實現管道操做。
TCP針對網絡中的小數據也有必定的優化策略:Nagle算法。
Nagle算法:
要求緩衝區的數據達到必定數量或者必定時間後纔將其發出,因此小數據包會被Nagle算法合併,所以來優化網絡。雖然網絡帶寬被有效地使用,可是數據有可能被延遲發送。
UDP全稱爲用戶數據包協議,與TCP同樣屬於網絡傳輸層。UDP和TCP最大的不一樣是UDP不是面向鏈接的。
建立UDP套接字十分的簡單,UDP套接字一旦被建立,既能夠做爲客戶端發送數據,也能夠做爲服務器端接收數據。
var dgram = rerquire('dgram');
var socket = dgram.createSocket("udp4");
複製代碼
想要UDP套接字接收網絡信息,只要調用dgram.bind(port,[address])方法對網卡和端口進行綁定便可。
建立UDP服務器端示例:
var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " +
rinfo.address + ":" + rinfo.port);
});
server.on("listening", function () {
var address = server.address();
console.log("server listening " +
address.address + ":" + address.port);
});
server.bind(41234);
複製代碼
建立UDP客戶端示例:
var dgram = require('dgram');
var message = new Buffer("深刻淺出Node.js");
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, 41234, "localhost", function (err, bytes) {
client.close();
});
複製代碼
UDP套接字只是一個EventEmitter的實例。自定義事件:
Node提供了基本的http和https模塊用於HTTP和HTTPS的封裝。
HTTP服務器的實現:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
複製代碼
初始HTTP
HTTP的全稱是超文本傳輸協議(HyperText Transfer Protocol)。
HTTP構建在TCP之上,屬於應用層協議。
HTTP報文
HTTP是基於請求響應式的,以一問一答的方式實現服務。
HTTP服務只作兩件事:處理HTTP請求和發送HTTP響應。
不管是HTTP請求報文仍是HTTP響應報文,報文內容都包含兩個部分:報文頭和報文體。
Node的http模塊包含對HTTP處理的封裝。
在Node中,HTPP服務繼承自TCP服務器(net模塊),它可以與多個客戶端保持鏈接,因爲其採用事件驅動的形式,並非爲每個鏈接建立額外的線程或進程,保持很低的內存佔用,因此可以實現高併發。
HTTP服務和TCP服務模型的區別在於,在開啓keepalive後,一個TCP會話能夠用於屢次請求和響應。TCP服務以connection爲單元進行服務,HTTP服務以request爲單位進行服務。
http模塊將鏈接所用套接字的讀寫抽象爲ServerRequest和ServerResponse對象,分別對應請求和響應操做。
HTTP請求
對於TCP鏈接的讀操做,http模塊將其封裝爲ServerRequest對象。
HTTP響應
HTTP響應對象封裝了對底層鏈接的寫操做,能夠將其看作一個可寫的流對象。
響應結束後,HTTP服務器可能會將當前的鏈接用於下一個請求,或者關閉鏈接。
HTTP服務的事件
HTTP服務也是個EventEmitter實例:
HTTP客戶端是服務器服務模型的另外一部分,處在HTTP的另外一端,在整個報文的參與中,報文頭和報文體由它產生。
HTTP響應
HTTP客戶端在CLientRequest對象中,它的事件叫作response。
HTTP代理
http提供的ClientRequest對象是基於TCP層實現的,在keepalive的狀況下,一個底層會話鏈接能夠屢次用於請求。爲了重用TCP鏈接,http模塊包含一個默認的客戶端代理對象http。globalAgent.t它對每一個服務器端(host+port)建立的鏈接進行了管理,默認狀況下,經過ClientRequest對象對同一個服務器發起的HTTP請求最多能夠建立5個鏈接。它的實質是一個鏈接池。
調用HTTP客戶端同時對一個服務器發起10次請求時,其實質只有5個請求處於併發狀態,後續的請求完成服務後才真正發出。這與瀏覽器對同一個域名有下載鏈接數的限制是相同的行爲。
HTTP客戶端事件
WebSocket與Node之間的配合堪稱完美的理由:
WebSocket與傳統HTTP的好處:
使用WebSocket,網頁客戶端只須要一個TCP鏈接便可完成雙向通訊,在服務器與客戶端頻繁通訊時,無須頻繁斷開鏈接和重發請求。
WebSocket與HTTP的區別:
相比HTTP,WebSocket更接近於傳輸層協議,並無在HTTP的基礎上模擬服務器端的推送,而是在TCP上定義的獨立的協議。
WebSocket協議主要分爲兩個部分:握手和數據傳輸。
一旦WebSocket握手成功,服務器端與客戶端將會呈現對等的效果,都能接收和發送消息。
在握手順利完成後,當前鏈接再也不進行HTTP的交互,而是開始WebSocket的數據幀協議。實現客戶端與服務器端的數據交換。
密鑰
TLS/SSL是一個公鑰/私鑰的結構,它是一個非對稱的結構,每一個服務器端和客戶端都有本身的公私鑰。
公鑰用來加密要傳輸的數據,私鑰用來解密接收到的數據。
公鑰和私鑰是配對的,經過公鑰加密的數據,只有經過私鑰才能解密,因此在創建安全傳輸以前,客戶端和服務器端之間須要互換公鑰。客戶端發送數據時要經過服務器端的公鑰進行加密,服務器端發送數據時則須要客戶端的公鑰進行加密。
公私鑰的非對稱加密雖好,可是網絡中依然可能存在竊聽的狀況,典型的例子就是中間人攻擊。
客戶端和服務器端在交換公鑰的過程當中,中間人對客戶端扮演服務器端的角色,對服務器端扮演客戶端的角色,所以客戶端和服務器端幾乎感覺不到中間人的攻擊。
爲了解決中間人攻擊,數據傳輸過程當中還須要對獲得的公鑰進行認證,以確認獲得的公鑰是出自目標服務器。
數字證書
爲了確保數據的安全,引入第三方:CA(Certificate Authority,數字證書認證中心)。
CA的做用是爲站點頒發證書,且這個證書中具備CA經過本身的公鑰和私鑰實現的簽名。
爲了獲得簽名證書,服務器端須要經過本身的私鑰生成CSR(Certificate Signing Request,證書籤名請求)文件。CA機構將經過這個文件頒發屬於該服務器的簽名證書,只要經過CA機構就能驗證證書是否合法。
與普通的TCP服務器端和客戶端相比,TLS的服務器端和客戶端僅僅只在證書的配置上有差異,其他部分基本相同。
HTTPS服務就是工做在TLS/SSL上的HTTP。