本文是WebSocket系列的第一篇,主要介紹WebSocket相關的基礎協議知識和API。因爲WebSocket的相關介紹在MDN中分佈較亂,初學者不太容易入門,所以經過本文將相關基礎知識和使用方法進行一個概括和總結。javascript
本文主要內容以下:html
經過本文,你可以瞭解到WebSocket相關基礎知識,同時瞭解到WebSocket在線上環境中是如何使用的。java
WebSockets 是一個能夠建立和服務器間進行雙向會話的高級技術。經過這個API你能夠向服務器發送消息並接受基於事件驅動的響應,這樣就不用向服務器輪詢獲取數據了。web
上面是MDN中關於WebSocket的說明。其中雙向會話
指的是客戶端和服務端都可以經過WebSocket來進行數據的互相傳遞,即服務端能夠給客戶端推送數據,客戶端也能夠經過WebSocket來傳遞數據。服務器
在不使用WebSocket時,若是咱們須要創建一條長鏈接,有如下幾種方法:websocket
下面,咱們對這幾個都進行簡單的介紹。網絡
輪詢是最先在客戶端用來模擬長鏈接的一種方式。他經過客戶端定時想服務端發送HTTP請求來模擬客戶端向服務端發送數據,而服務端的數據則是在客戶端發送HTTP請求後跟隨返回。socket
這種方案可以讓客戶端的數據幾乎實時的到達,可是缺點也顯而易見:服務端的數據須要在客戶端的請求回來後才能帶回。若是HTTP請求的間隔過短,則會致使大量的網絡開銷;若是間隔太長,這將致使數據傳遞的不及時。函數
長輪詢是在輪詢的基礎上改進的一種方式。在客戶端發送HTTP請求且服務端收到請求時,服務端會先維持這個請求不返回。在特定的時間內(通常爲30秒,由於一般HTTP判斷超時時間爲30秒),若是服務端沒有數據,則迴應這個請求;服務端有數據須要發送時,則當即經過HTTP請求的響應將數據傳遞給客戶端。客戶端收到響應後,當即發起下一次的HTTP請求。性能
這種方案可以解決輪詢中帶來的服務端數據不能及時傳遞的問題,可是帶來的網絡花銷大的問題仍然沒法解決。
SSE是一個新的協議,做用爲服務端想客戶端推送數據。他經過自定義的SSE協議來實現單項的數據推送。SSE的缺點是數據只能從服務端像客戶端傳遞,而數據不能經過客戶端向服務端傳遞。
WebSocket可以有效的解決如下問題:
其餘的優勢能夠參考維基百科。
瞭解了爲何須要使用WebSocket,下面讓咱們來了解下WebSocket協議相關的內容。
WebSocket協議是經過HTTP協議升級而來。只須要在HTTP協議基礎上增長兩次握手,便可創建WebSocket鏈接(若是是須要經過SSL加密,則還須要進行SSL握手過程),握手的部分詳情能夠見WebSocket文檔,下面咱們簡單介紹如下Header相關字段。
請求Header以下:
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
複製代碼
其中:
Host: server.example.com
:表示將要鏈接的WebSocket地址。Connection: Upgrade
:須要升級HTTP鏈接。Upgrade: websocket
:將HTTP鏈接升級至WebSocket鏈接。Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==
:客戶端生成的WebSocket鏈接密鑰。Sec-WebSocket-Protocol: chat, superchat
:指定哪些協議是客戶端能夠接受的。Sec-WebSocket-Version: 13
:WebSocket版本號。HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
複製代碼
其中:
Upgrade: websocket
:確認將HTTP鏈接升級至WebSocket鏈接。Connection: Upgrade
:確認升級HTTP鏈接。Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo
:服務端根據客戶端的鏈接密鑰生成的服務端密鑰。Sec-WebSocket-Protocol: chat
:選擇的WebSocket協議。對WebSocket的協議有了一個初步的瞭解,下面讓咱們看下,在具體的使用場景中,如何使用WebSocket。
WebSocket的API很少,下面咱們就根據使用的順序:
來逐一進行介紹,具體的MDN資料能夠見此處。
WebSocket經過初始化實例來創建鏈接,經過open
事件回調函數來確認鏈接創建成功,具體示例以下:
const webSocket = new WebSocket('ws://server.example.com');
webSocket.addEventListener('open', (event) => {
// 創建鏈接成功
});
複製代碼
在WebSocket創建ws鏈接時,url能夠是域名或者IP地址;可是當創建的鏈接是wss(加密WebSocket)時,url必須是域名,由於須要配置相應的證書,而證書是針對域名的。
WebSocket經過message
事件來接收消息。
socket.addEventListener('message', function (event) {
console.log('Message from server', event.data);
});
複製代碼
WebSocket能夠傳遞String
、ArrayBuffer
和Blob
三種數據類型,所以在收到消息時多是其中的任意一種。其中,String
和ArrayBuffer
使用的最多。
若是是String
類型,直接經過字符串處理函數便可進行相關轉換,如JSON等格式。
若是是二進制ArrayBuffer
類型,則須要使用DataView
來進行處理,相關的內容將在本系列第二篇中進行介紹。
WebSocket經過send
方法來發送消息。
webSocket.send(data);
複製代碼
示例中的data
字段,也有多是收到消息所說的String
、ArrayBuffer
和Blob
三種數據類型之一。其中,Blob
做爲一種類文件數據類型,再此不進行過多介紹。咱們使用最多的就是String
和ArrayBuffer
。
String
類型只須要傳遞一個字符串給send
方法做爲參數便可。ArrayBuffer
類型則須要傳遞一個ArrayBuffer對象做爲參數,相關的內容也將在本系列第二篇中進行介紹。當服務端主動關閉WebSocket鏈接時,會經過WebSocket向客戶端發送一個close數據包,WebSocket的close
事件會觸發。
webSocket.addEventListener('close', (closeEvent) => {
});
複製代碼
注:當網絡斷開時,WebSocket鏈接並不會被動關閉,由於沒有收到關閉的數據包。
客戶端能夠經過WebSocket提供的close
方法來主動關閉長鏈接。
webSocket.close();
複製代碼
目前該方法有兩個參數(在某些版本中不支持,詳情見MDN文檔):
本文主要是介紹了一下WebSocket相關的基礎知識。
經過WebSocket的長鏈接,客戶端和服務端能夠進行大量的數據傳輸而不會帶來相關的性能問題,這給Web端帶來了極大的功能加強。目前Web端可使用WebSocket來進行IM相關功能開發,或者實時協做等須要與服務端進行大量數據交互的功能,而且不須要像以前同樣使用長輪詢的Hack方式來實現。
具體的使用方式和線上的使用問題,將會在本系列後幾篇博客中進行介紹。