WebSocket是一種用於在服務器與客戶端之間實現高效的雙向通訊的機制。能夠解決數據實時性要求比較高的應用,好比:在線聊天,在線教育,炒股或定位等。html
一:websocket產生背景:node
爲了解決這種實時性的問題,有幾種替代方案:web
一、輪詢json
概念:客戶端經過必定的時間間隔以頻繁請求的方式向服務器發送請求,來保持客戶端和服務器端的數據同步;api
缺點:當客戶端以固定頻率向服務器端發送請求時,服務器端的數據可能並無更新,帶來不少無謂請求,浪費帶寬,效率低下瀏覽器
二、Comet技術(長輪詢)服務器
概念:長輪詢在客戶端發送請求後,服務器保留響應,並維持鏈接,能夠在任意時間點從服務器返回響應。而客戶端在收到響應的同時再次向服務器創建鏈接。實例:WebQQwebsocket
缺點:與輪詢相比,長輪詢避免了沒必要要的通訊過程,但也須要在有更新時再次鏈接網絡
三、Comet技術(流技術)app
概念:經過由客戶端發出第一個請求,創建鏈接,並在維持該鏈接的同時從服務器不斷向客戶端返回響應
缺點:服務器維護一個長鏈接會增長開銷
傳統實時性技術的通訊數據流以下圖:
二:websocket的運行機制
一、WebSocket只有在創建握手鍊接的時候借用了HTTP協議的頭,鏈接成功後的通訊部分都是基於TCP的鏈接,它與 HTTP 之間的惟一關係就是它的握手請求能夠做爲一個升級請求(Upgrade request)經由 HTTP 服務器解釋
二、WebSocket 請求響應客戶端服務器交互圖
只通過一次握手便可進行雙向通訊。
三、WebSocket 協議優勢:
1. Header
互相溝通的Header是很小的-大概只有 2 Bytes
2. Server Push
服務器的推送,服務器再也不被動的接收到瀏覽器的請求以後才返回數據,而是在有新數據時就主動推送給瀏覽器
4.websocket的api
websocket中有兩個方法:
一、send() 向遠程服務器發送數據
二、close() 關閉該websocket連接
websocket同時還定義了幾個監聽函數
一、onopen 當網絡鏈接創建時觸發該事件
二、onerror 當網絡發生錯誤時觸發該事件
三、onclose 當websocket被關閉時觸發該事件
四、onmessage 當websocket接收到服務器發來的消息的時觸發的事件,也是通訊中最重要的一個監聽事件。
五、websocket還定義了一個readyState屬性:
一、CONNECTING(0) websocket正嘗試與服務器創建鏈接
二、OPEN(1) websocket與服務器已經創建鏈接
三、CLOSING(2) websocket正在關閉與服務器的鏈接
四、CLOSED(3) websocket已經關閉了與服務器的鏈接
簡單的客戶端與服務器通訊的案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>webSocket示例</title> </head> <body> <h1>Echo Test</h1> <input id="sendTxt" type="text" /> <button id="sendBtn">發送</button> <div id="recv"></div> <script> //建立websocket實例 var websocket=new WebSocket('ws://echo.websocket.org'); //‘ws://echo.websocket.org’是websocket測試的服務器,把你的數據原封不動的返回給你 //創建鏈接後的事件 websocket.onopen=function(){ console.log('websocket open'); document.getElementById('recv').innerHTML='Connected'; } //關閉鏈接 websocket.onclose==function(){ console.log('websocket close'); } //客戶端接收到數據觸發 websocket.onmessage=function(e){ console.log(e.data); document.getElementById('recv').innerHTML=e.data; } //點擊發送按鈕觸發 document.getElementById('sendBtn').onclick=function(){ var txt=document.getElementById('sendTxt').value; document.getElementById('recv').innerHTML=txt; } </script> </body> </html>
直接瀏覽器打開文件,便可運行。
按F12觀察一下
協議是ws協議,且狀態是101正在鏈接的狀態。
4、下面是製做一個簡單聊天室功能
須要nodejs做服務器後臺
package.json文件(下載nodejs-websocket模塊)
{ "name": "demo2", "version": "1.0.0", "description": "", "main": "wsServer.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "nodejs-websocket": "^1.7.1" } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>webSocket示例</title> </head> <body> <h1>Echo Test</h1> <input id="sendTxt" type="text" /> <button id="sendBtn">發送</button> <div id="recv"></div> <script> var websocket=new WebSocket('ws://localhost:8001/'); function showMessage(str){ var div=document.createElement('div'); div.innerHTML=str; document.body.appendChild(div); } //創建鏈接 websocket.onopen=function(){ console.log('websocket open'); document.getElementById('sendBtn').onclick=function(){ var txt=document.getElementById('sendTxt').value; if(txt){ websocket.send(txt); //發送數據給服務器 } } } //關閉鏈接 websocket.onclose==function(){ console.log('websocket close'); } //客戶端接收數據觸發 websocket.onmessage=function(e){ console.log(e.data); showMessage(e.data); } </script> </body> </html>
wsServer.js
var ws = require("nodejs-websocket"); var clientCount=0; var server = ws.createServer(function (conn) { console.log("New connection") clientCount++; conn.nickname='user'+clientCount; boradcast(conn.nickname+' comes in'); //服務端接收到消息後觸發 conn.on("text", function (str) { boradcast(conn.nickname+' says: '+str); }) //關閉鏈接 conn.on("close", function (code, reason) { console.log("Connection closed"); boradcast(conn.nickname+' left'); }) // conn.on("error",function(err){ console.log("handle err"); console.log(err); }) }).listen(8001); function boradcast(str){ server.connections.forEach(function(connection){ connection.sendText(str); }) }
運行node wsServer.js
運行node以後,直接打開瀏覽器瀏覽文件,一個文件表明一個用戶,這樣就能夠兩邊對話了。
這個h5的新協議仍是頗有趣的。
推薦去看一下:http://www.imooc.com/learn/861 websocket案例講解。