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