WebSocket
是一種網絡通信協議。
為什么需要 WebSocket?
因為HTTP
協議有一個缺陷:通信只能由客戶端發起。這種單向請求的特點,注定了如果服務器有連續的狀態變化,客戶端要獲知就非常麻煩。我們只能使用"輪詢":每隔一段時候,就發出一個詢問,了解服務器有沒有新的信息。
輪詢技術有:(短)輪詢(Polling
),Comet
的長輪詢(Long-polling
)和流技術(Http Streaming
)等。
輪詢的效率低,非常浪費資源。所以websocket
就應用而生了。
W3C 在 HTML5
中提供了一種client
與 server
間進行全雙工通訊的網絡技術WebSocket
。WebSocket
是一個全新的、獨立的協議,基于 TCP
協議,與HTTP
協議兼容卻不會融入HTTP
協議,僅僅作為 HTML5
的一部分。
WebSocket原理
WebSocket
是一種協議,是一種與HTTP
同等的網絡協議,兩者都是應用層協議,都基于 TCP
協議。但是 WebSocket
是一種雙向通信協議,在建立連接之后,WebSocket
的 server
與 client
都能主動向對方發送或接收數據。同時,WebSocket
在建立連接時需要借助 HTTP
協議,連接建立好了之后 client
與 server
之間的雙向通信就與 HTTP
無關了。
相比于傳統HTTP
的每次“請求-應答”都要client 與 server
建立連接的模式,WebSocket
是一種長連接的模式。就是一旦WebSocket
連接建立后,除非client
或者 server
中有一端主動斷開連接,否則每次數據傳輸之前都不需要HTTP
那樣請求數據。
接下來,從報文層面談一下WebSocket
與 HTTP
的差異。
首先,client
發起WebSocket
連接,報文類似于 HTTP
,但主要有幾點不一樣的地方:
Upgrade: websocket
: 表明這是一個WebSocket
類型請求,意在告訴server
需要將通信協議切換到WebSocket
。Sec-WebSocket-Key
: 是client
發送的一個base64
編碼的密文,要求server
必須返回一個對應加密的Sec-WebSocket-Accept
應答,否則client
會拋出Error during WebSocket handshake
錯誤,并關閉連接。
server
收到報文后,如果支持WebSocket
協議,那么就會將自己的通信協議切換到WebSocket
,返回以下信息:
-
HTTP/1.1 101 WebSocket Protocol Handshake
:返回的狀態碼為101
,表示同意client
的協議轉換請求。 Upgrade: websocket
Connection: Upgrade
-
Sec-WebSocket-Accept:
...
以上都是利用HTTP
協議完成的。這樣,經過“請求-相應”的過程, server
與client
的 WebSocket
連接握手成功,后續便可以進行TCP
通訊了,也就沒有HTTP
什么事了。
WebSocket通信特點
最大特點就是,服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話,屬于服務器推送技術的一種。
建立在
TCP
協議之上,服務器端的實現比較容易。與
HTTP
協議有著良好的兼容性。默認端口也是80
和443
,并且握手階段采用HTTP
協議,因此握手時不容易屏蔽,能通過各種HTTP
代理服務器。數據格式比較輕量,性能開銷小,通信高效。
可以發送文本,也可以發送二進制數據。
沒有同源限制,客戶端可以與任意服務器通信。
協議標識符是
ws
(如果加密,則為wss
),服務器網址就是URL
。
WebSocket實例
客戶端實例
var ws = new WebSocket("(wss://echo.websocket.org/)");
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
ws.onclose = function(evt) {
console.log("Connection closed.");
};
客戶端API
-
WebSocket
對象作為一個構造函數,用于新建WebSocket
實例。
var ws = new WebSocket('ws://localhost:8000');
執行上面語句之后,客戶端就會與服務器進行連接。
-
webSocket.readyState
返回實例對象的當前狀態,值為:
CONNECTING
:值為0
,表示正在連接。
OPEN
:值為1
,表示連接成功,可以通信了。
CLOSING
:值為2
,表示連接正在關閉。
CLOSED
:值為3
,表示連接已經關閉,或者打開連接失敗。 -
webSocket.onopen
用于指定連接成功后的回調函數,也可以使用addEventListener
方法。 -
webSocket.onclose
用于指定連接關閉后的回調函數。 -
webSocket.onmessage
用于指定收到服務器數據后的回調函數,也可以使用addEventListener
方法。 -
webSocket.send()
用于向服務器發送數據。 -
webSocket.bufferedAmount
表示還有多少字節的二進制數據沒有發送出去。它可以用來判斷發送是否結束。 -
webSocket.onerror
用于指定報錯時的回調函數,也可以使用addEventListener
方法。
WebSocket 服務器的實現可以使用node
中的μWebSockets,Socket.IO,WebSocket-Node