WebSocket系列之基礎知識入門篇

概述

本文是WebSocket系列的第一篇,主要介紹WebSocket相關的基礎協議知識和API。因爲WebSocket的相關介紹在MDN中分佈較亂,初學者不太容易入門,所以經過本文將相關基礎知識和使用方法進行一個概括和總結。javascript

本文主要內容以下:html

  • WebSocket基礎概念介紹
  • WebSocket協議初讀
  • WebSocket 相關API淺析
  • WebSocket在線上項目中的使用

經過本文,你可以瞭解到WebSocket相關基礎知識,同時瞭解到WebSocket在線上環境中是如何使用的。java

WebSocket介紹

WebSockets 是一個能夠建立和服務器間進行雙向會話的高級技術。經過這個API你能夠向服務器發送消息並接受基於事件驅動的響應,這樣就不用向服務器輪詢獲取數據了。web

上面是MDN中關於WebSocket的說明。其中雙向會話指的是客戶端和服務端都可以經過WebSocket來進行數據的互相傳遞,即服務端能夠給客戶端推送數據,客戶端也能夠經過WebSocket來傳遞數據。服務器

爲何要使用WebSocket

在不使用WebSocket時,若是咱們須要創建一條長鏈接,有如下幾種方法:websocket

  • 輪詢
  • 長輪詢(經常使用)
  • SSE(Server Send Event)

下面,咱們對這幾個都進行簡單的介紹。網絡

輪詢

輪詢是最先在客戶端用來模擬長鏈接的一種方式。他經過客戶端定時想服務端發送HTTP請求來模擬客戶端向服務端發送數據,而服務端的數據則是在客戶端發送HTTP請求後跟隨返回。socket

這種方案可以讓客戶端的數據幾乎實時的到達,可是缺點也顯而易見:服務端的數據須要在客戶端的請求回來後才能帶回。若是HTTP請求的間隔過短,則會致使大量的網絡開銷;若是間隔太長,這將致使數據傳遞的不及時。函數

長輪詢

長輪詢是在輪詢的基礎上改進的一種方式。在客戶端發送HTTP請求且服務端收到請求時,服務端會先維持這個請求不返回。在特定的時間內(通常爲30秒,由於一般HTTP判斷超時時間爲30秒),若是服務端沒有數據,則迴應這個請求;服務端有數據須要發送時,則當即經過HTTP請求的響應將數據傳遞給客戶端。客戶端收到響應後,當即發起下一次的HTTP請求。性能

這種方案可以解決輪詢中帶來的服務端數據不能及時傳遞的問題,可是帶來的網絡花銷大的問題仍然沒法解決。

SSE(Server Send Event)

SSE是一個新的協議,做用爲服務端想客戶端推送數據。他經過自定義的SSE協議來實現單項的數據推送。SSE的缺點是數據只能從服務端像客戶端傳遞,而數據不能經過客戶端向服務端傳遞。

WebSocket可以解決上述問題

WebSocket可以有效的解決如下問題:

  1. 帶寬問題:WebSocket相對於HTTP來講協議頭更加小,同時按需傳遞。
  2. 數據實時性問題:WebSocket相對於輪詢和長輪詢來講,可以實時傳遞數據,延遲更小。
  3. 狀態問題:相較於HTTP的無狀態請求,WebSocket在創建鏈接後可以維持特定的狀態。

其餘的優勢能夠參考維基百科

WebSocket協議

瞭解了爲何須要使用WebSocket,下面讓咱們來了解下WebSocket協議相關的內容。

WebSocket協議是經過HTTP協議升級而來。只須要在HTTP協議基礎上增長兩次握手,便可創建WebSocket鏈接(若是是須要經過SSL加密,則還須要進行SSL握手過程),握手的部分詳情能夠見WebSocket文檔,下面咱們簡單介紹如下Header相關字段。

請求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版本號。

響應Header

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 API介紹

對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能夠傳遞StringArrayBufferBlob三種數據類型,所以在收到消息時多是其中的任意一種。其中,StringArrayBuffer使用的最多。

  • 若是是String類型,直接經過字符串處理函數便可進行相關轉換,如JSON等格式。

  • 若是是二進制ArrayBuffer類型,則須要使用DataView來進行處理,相關的內容將在本系列第二篇中進行介紹。

發送消息

WebSocket經過send方法來發送消息。

webSocket.send(data);
複製代碼

示例中的data字段,也有多是收到消息所說的StringArrayBufferBlob三種數據類型之一。其中,Blob做爲一種類文件數據類型,再此不進行過多介紹。咱們使用最多的就是StringArrayBuffer

  • String類型只須要傳遞一個字符串給send方法做爲參數便可。
  • ArrayBuffer類型則須要傳遞一個ArrayBuffer對象做爲參數,相關的內容也將在本系列第二篇中進行介紹。

關閉鏈接

被動關閉

當服務端主動關閉WebSocket鏈接時,會經過WebSocket向客戶端發送一個close數據包,WebSocket的close事件會觸發。

webSocket.addEventListener('close', (closeEvent) => {
    
});
複製代碼

注:當網絡斷開時,WebSocket鏈接並不會被動關閉,由於沒有收到關閉的數據包。

主動關閉

客戶端能夠經過WebSocket提供的close方法來主動關閉長鏈接。

webSocket.close();
複製代碼

目前該方法有兩個參數(在某些版本中不支持,詳情見MDN文檔):

  • 第一個參數表示關閉鏈接的狀態號,默認爲1000,表示正常關閉。
  • 第二個參數爲關閉緣由,是一個不長於123字節的UTF-8文本。

總結

本文主要是介紹了一下WebSocket相關的基礎知識。

經過WebSocket的長鏈接,客戶端和服務端能夠進行大量的數據傳輸而不會帶來相關的性能問題,這給Web端帶來了極大的功能加強。目前Web端可使用WebSocket來進行IM相關功能開發,或者實時協做等須要與服務端進行大量數據交互的功能,而且不須要像以前同樣使用長輪詢的Hack方式來實現。

具體的使用方式和線上的使用問題,將會在本系列後幾篇博客中進行介紹。

相關文章
相關標籤/搜索