好程序員web前端分享WebSocket協議,WebSocket協議簡介
一.WebSocket協議簡介
1. WebSocket是html5規範新引入的功能,用於解決瀏覽器與後臺服務器雙向通信的問題,使用WebSocket技術,後臺能夠隨時向前端推送消息,以保證先後臺狀態統一,在傳統的無狀態HTTP協議中,這是「沒法作到」的。
2. 在WebSocket出現以前,傳統的服務端向瀏覽器推送消息的技術包括:ajax、flash、comet、java applet等。無一例外,這些技術使用的都是長輪循,即每隔一段時間去請求後臺,以獲取最新狀態。長輪詢方式容易實現,但效果也差,頻繁盲目的調用後臺,帶來沒必要要的開銷,且實時性沒法保障,後臺出現更新,前端須要在下一次輪詢時才知道。
3. WebSocket協議支持服務端與瀏覽器創建長鏈接,雙方能夠隨時發送數據給對方,再也不是由客戶端控制的一問一答的方式。在實現推送功能的時候,主要是由服務端給客戶端發送數據。
4.之前的網站爲了實現推送功能,使用的方法都是輪詢。所謂的輪詢就是在特定的時間間隔(例如1秒),由瀏覽器向服務器發出一個 Http request ,而後服務器返回最新的數據給客戶端瀏覽器,從而給出一種服務端實時推送的假象。因爲 Http Request 的 Header(請求頭)很長,而傳輸的數據可能很短就只佔一點點,每次請求消耗的帶寬大部分都消耗在 Header 上。從網上資料得知後來還有改進的輪詢方法叫作 Comet ,使用 Ajax 。但這種技術雖然可達到雙向通訊。
二.WebSocket原理
基於長輪循(polling)和websocket推送的瀏覽器(browser)和服務端(Server)的交互對比圖以下所示:html
因爲WebSocket協議創建在http協議的基礎之上,所以兩者有不少的相似之處。事實上,在使用websocket協議時,瀏覽器與服務端最開始創建的仍是http鏈接,以後再將協議從http轉換成websocket,協議轉換的過程稱之爲握手(handshake),表示服務端與客戶端都贊成創建websocket協議。須要注意的是,因爲websocket是新的協議,須要瀏覽器和web服務端都支持的狀況下,才能創建鏈接成功。正常狀況下,鏈接在創建的時候,瀏覽器向服務端發送一個HTTP請求,經過包含一些額外信息,代表其但願將協議從HTTP轉換成WebSocket。這個額外信息實際上就是增長了一個請求頭Update,以下所示:前端
熟悉 HTTP 的童鞋可能發現了,這段相似 HTTP 協議的握手請求中,多了這麼幾個東西。html5
這個就是 WebSocket 的核心了,告訴 Apache 、 Nginx 等服務器:注意啦,我發起的請求要用 WebSocket 協議,快點幫我找到對應的助理處理~而不是那個老土的 HTTP。java
首先, Sec-WebSocket-Key 是一個 Base64 encode 的值,這個是瀏覽器隨機生成的,告訴服務器:泥煤,不要忽悠我,我要驗證你是否是真的是 WebSocket 助理。程序員
而後, Sec_WebSocket-Protocol 是一個用戶定義的字符串,用來區分同 URL 下,不一樣的服務所須要的協議。簡單理解:今晚我要服務A,別搞錯啦~web
最後, Sec-WebSocket-Version 是告訴服務器所使用的 WebSocket Draft (協議版本),在最初的時候,WebSocket 協議還在 Draft 階段,各類奇奇怪怪的協議都有,並且還有不少期奇奇怪怪不一樣的東西,什麼 Firefox 和 Chrome 用的不是一個版本之類的,當初 WebSocket 協議太多但是一個大難題。不過如今還好,已經定下來啦~你們都使用同一個版本: 服務員,我要的是13歲的噢→_→ajax
而後服務器會返回下列東西,表示已經接受到請求, 成功創建 WebSocket 啦!瀏覽器
能夠在如下網址看到目前支持webscoket協議的主流瀏覽器和版本:服務器
支持html5的瀏覽器,通常都會提供一個內置的js對象Websocket ,開發者利用這個對象就能夠與服務端創建websocket鏈接。特別的在FireFox中,這個對象爲在Firefox中爲MozWebSocket。
能夠經過如下js代碼檢測一個瀏覽器是否支持websocketwebsocket
Websocket對象還提供了幾個回調方法 //鏈接建立成功時被回調 myWebSocket.onopen = function(evt) { alert("Connection open ..."); }; //收到服務端的消息時被回調 myWebSocket.onmessage = function(evt) { alert( "Received Message: " + evt.data); }; //鏈接關閉時被回調 myWebSocket.onclose = function(evt) { alert("Connection closed."); };