通訊只能由客戶端主動發起請求來獲取服務端數據javascript
WebSocket是一種能夠建立和服務器間進行 雙向會話 的高級技術,經過WebSocket能夠向服務器發送消息並接受基於事件驅動的響應。這樣就不用向服務器輪詢獲取數據。html
雙向會話:客戶端和服務端都可以經過WebSocket來進行數據相互傳遞,即服務端能夠給客戶端推送數據,客戶端也能夠經過WebSocket向服務端傳遞數據。java
在不使用WebSocket時,咱們須要創建長鏈接時。創建長鏈接的幾種主要方法:web
輪詢是最先在客戶端用來模擬長鏈接的一種方式。他經過客戶端定時向服務端發送HTTP請求來模擬客戶端向服務端發送數據,而服務端的數據則是在客戶端發送HTTP請求後跟隨返回
缺點: 服務端的數據須要在客戶端的請求回來後才能帶回。若是HTTP請求的間隔過短,則會致使大量的網絡開銷;若是間隔太長,這將致使數據傳遞的不及時。api
長輪詢是在輪詢的基礎上改進的一種方式。在客戶端發送HTTP請求且服務端收到請求時,服務端會先維持這個請求不返回。在特定的時間內(通常爲30秒,由於一般HTTP判斷超時時間爲30秒),若是服務端沒有數據,則迴應這個請求;服務端有數據須要發送時,則當即經過HTTP請求的響應將數據傳遞給客戶端。客戶端收到響應後,當即發起下一次的HTTP請求。
優缺點:可以解決輪詢中帶來的服務端數據不能及時傳遞的問題,可是帶來的網絡花銷大的問題仍然沒法解決。服務器
SSE一種新的協議,用於服務端向客戶端推送數據,經過SSE實現數據的單向推送功能。
缺點: 單向推送,只能從服務端向客戶端推送數據、websocket
WebSocket可以有效的解決上述問題,還包括如下問題:網絡
WebSocket協議是由HTTP協議升級而來的,只要在HTTP協議的基礎上增長兩次握手(若是是須要經過SSL加密,則還須要進行SSL握手過程),便可創建WebSocket鏈接。如下Header相關字段socket
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13性能
其中:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
其中:
WebSocket的API比較簡單,按使用順序包括:
WebSocket 經過實例化來建立鏈接,經過實例的open事件的回調來確認鏈接建立成功,如:
const websocket = new WebSocket('ws://server.example.com'); websocket.addEventListener('open', e => { // 創建鏈接成功... });
ps:在WebSocket創建ws鏈接時,url能夠是域名或者IP地址;可是當創建的鏈接是wss(加密WebSocket)時,url必須是域名,由於須要配置相應的證書,而證書是針對域名的。
WebSocket 經過message事件來監聽消息接收,如:
websocket .addEventListener('message', e => { // 消息接收成功 });
WebSocket能夠傳遞String、ArrayBuffer和Blob三種數據類型,所以在收到消息時多是其中的任意一種。其中,String和ArrayBuffer使用的最多。
WebSocket 的發送消息是經過實例的send方法來實現的。
websocket.send(data);
當服務端被動關閉WebSocket鏈接時,會經過WebSocket向客戶端發送一個close數據包,會觸發實例的WebSocket close事件如:
websocket.addEventListener('close', e => { // WebSocket鏈接關閉 });
注:當網絡斷開時,WebSocket鏈接並不會被動關閉,由於沒有收到關閉的數據包。
客戶端能夠經過WebSocket提供的close方法來主動關閉長鏈接
websocket.close();
注:主動關閉不會觸發close事件。
websocket.readyState
readyState
屬性返回實例對象的當前狀態,共有四種
- CONNECTING 值爲0 表示正在鏈接
- OPEN 值爲1 表示已經鏈接,能夠通訊
- CLOSING 值爲2 表示鏈接正在關閉
- CLOSED 值爲3 表示鏈接已經關閉
websocket.bufferedAmount
實例對象的bufferedAmount
屬性,表示還有多少字節的二進制數據沒有發送出去,能夠經過該屬性來判斷數據發送是否結束。
var data = new ArrayBuffer(10000000); socket.send(data); if (socket.bufferedAmount === 0) { // 發送完畢 } else { // 發送還沒結束 }
websocket.binaryType
binaryType
屬性,顯式指定收到的二進制數據類型
// 收到的是 blob 數據 websocket.binaryType = "blob"; websocket.onmessage = function(e) { console.log(e.data.size); }; // 收到的是 ArrayBuffer 數據 websocket.binaryType = "arraybuffer"; websocket.onmessage = function(e) { console.log(e.data.byteLength); };
經過WebSocket的長鏈接,客戶端和服務端能夠進行大量的數據傳輸而不會帶來相關的性能問題,這給Web端帶來了極大的功能加強。目前Web端可使用WebSocket來進行IM相關功能開發,或者實時協做等須要與服務端進行大量數據交互的功能,而且不須要像以前同樣使用長輪詢的Hack方式來實現。