WebSocket系列之二進制數據設計與傳輸

概述

經過前三篇博客,咱們可以瞭解在經過WebSocket發送數據以前,咱們須要傳遞的數據是如何變成ArrayBuffer二進制數據的;在咱們收到二進制數據以後,咱們又如何將其變成了JavaScript中的常見數據類型。 本文做爲WebSocket系列的第四篇內容,將會用一個簡單的IM聊天應用把整個WebSocket傳輸二進制數據類型的內容鏈接起來,讓用戶對整個WebSocket傳輸二進制數據的方法有個瞭解。 本文的主要內容以下:javascript

  • 如何設計一個二進制協議
  • WebSocket如何發送二進制數據
  • WebSocket如何處理接收的二進制數據

以前的博客咱們介紹過了WebSocket基礎知識,數字類型和字符串類型與二進制數據間的轉換,若是沒有相關的基礎,建議先依次閱讀如下文章:java

如何設計一個二進制協議

什麼是協議

協議,網絡協議的簡稱,網絡協議是通訊計算機雙方必須共同聽從的一組約定。如怎麼樣創建鏈接、怎麼樣互相識別等。只有遵照這個約定,計算機之間才能相互通訊交流。它的三要素是:語法、語義、時序。web

經過百度百科中的介紹,咱們對協議的概念有了一個基礎的瞭解。通俗來講,協議就是通訊雙方約定好的一套規則。json

爲何要設計協議

沒有規矩不成方圓。通訊雙方只有經過協議,纔可以識別對方發送的數據內容。bash

咱們應該如何設計這套協議

首先,協議的設計應該可以區分不一樣的各個數據包;其次,它還須要具有必定的兼容性。 根據上述兩點要求,咱們設計了一套簡單的IM聊天協議,支持文本、圖片、文件三種消息。這套協議是按照最簡單的思路來設計的,所以也只是給你們一個參考的觀點,在真正的線上使用場景中,協議會比本文中的複雜和更加有層次。具體格式以下:websocket

{
    "id": "short", // 消息類型,1是文本協議格式;2是圖片協議格式;3是文件協議格式
    "sender": "long", // 發送用戶惟一id
    "reciever": "long", // 接受用戶惟一id
    "data": "string" // 消息內容,若是是文本協議則爲文本內容;若是是圖片協議則爲圖片地址;若是是文件協議則爲文件地址
}
複製代碼

這套協議如何使用

發送消息

從協議格式可知,將上述數據按照上述固定順序放入ArrayBuffer中,便可獲得一個有特定含義的二進制數據。例如:網絡

{
    "id": 1,
    "sender": "123",
    "reciever": "456",
    "data": "Hellow World"
}
複製代碼

當咱們須要發送此消息時,只須要:socket

  1. 在前2個Byte放入id
  2. 接下來8個Byte中放入sender
  3. 再接下來8個Byte放入reciever
  4. 最後緊接着放入一個string類型(以WebSocket系列之字符串如何與二進制數據進行轉換博客中的格式爲例,先將字符串長度構形成一個int類型,放在前4個Byte中,接下來將string類型編碼後放入)。 此數據就徹底按照協議構造完成了。咱們只需將次協議經過WebSocket發送便可。具體方法將會在後面章節中說明。

接收消息

從協議格式可知,當咱們收到一條消息時,只須要按照協議規範來進行反向解析便可。例如:post

{
    "id": 1,
    "sender": "123",
    "reciever": "456",
    "data": "Hellow World"
}
複製代碼

若是發送端發送的數據仍然爲此消息,咱們的解析順序爲:ui

  1. 先根據前2個Byte讀取一個Short類型的id數值。
  2. 將接下來的8個Byte讀取爲Long類型的sender字段。
  3. 再接下來的8個Byte讀取爲Long類型的reciever字段。
  4. 接下來讀取一個string類型(以發送消息這一節的數據爲例,先讀取4個Byte長度的int類型字符串長度,而後再根據長度讀取字符串便可)。

擴展此協議

當此協議字段沒法知足而且已經在線上使用時,咱們應該如何擴展呢? 根據咱們的寫入和讀取步驟,咱們能夠知道:**每次咱們讀取的二進制數據能夠認爲是一個格式固定的數據(string類型在構造時會有長度信息,所以認爲也是長度相對固定),因此咱們在讀取二進制數據時讀取的長度也是固定的。**所以,咱們在擴展時只須要往協議後面增長字段便可。

  • 擴展前的應用仍然會讀取以前已經肯定的數據協議,只須要保證內容不變,那麼功能也不會變。
  • 擴展後的應用可以解析擴展後的協議,所以獲得更多的數據,從而能夠實現更多的功能。

WebSocket如何發送二進制數據

經過如何設計一個二進制協議一章,咱們知道了如何定義WebSocket傳輸的二進制數據格式。下面,咱們來看下如何在WebSocket中發送二進制數據:

let arrayBuffer = getArrayBufferMessagesFromUser(); // 獲取用戶須要發送的消息數據,爲一個ArrayBuffer對象
let webSocket = getWebSocket(); // 獲取已經鏈接成功的WebSocket實例

websocket.binaryType = 'arraybuffer'; // 指定WebSocket接受ArrayBuffer實例做爲參數

webSocket.send(arrayBuffer);
複製代碼

經過上面的示例咱們能夠知道,WebSocket在發送string類型的數據或者ArrayBuffer類型的數據時,使用的API接口都是send方法,咱們只須要在WebSocket初始化後指定傳輸類型binaryType便可。

WebSocket如何處理接收的二進制數據

經過WebSocket如何發送二進制數據一章,咱們知道了如何發送二進制數據。接下來,讓咱們開看下如何處理WebSocket接收到的二進制數據:

let webSocket = getWebSocket(); // 獲取已經鏈接成功的WebSocket實例

websocket.binaryType = 'arraybuffer'; // 指定WebSocket接受ArrayBuffer實例做爲參數

webSocket.addEventListener('message', (message) => {
    let arrayBuffer = message.data; // 獲取用戶接收到的消息數據,爲一個ArrayBuffer對象
    let data = parseMessage(arrayBuffer); // 解析二進制數據
});
複製代碼

經過上面的示例咱們能夠知道,當咱們在創建鏈接時指定了傳輸類型binaryType爲ArrayBuffer以後,咱們經過WebSocket收到的數據也是一個ArrayBuffer實例。咱們只須要根據第一章講解的方式進行解析便可。

總結

本文做爲WebSocket系列的第四篇,經過一個IM聊天應用的示例將前三篇博客分享的內容串聯起來,給讀者完整介紹了在WebSocket中使用二進制數據進行傳輸的方法以及相關的數據類型轉換。 經過前面4篇博客的內容,讀者能夠根據本身的需求快速的構造和封裝WebSocket進行二進制數據傳輸,基本可以串聯整個應用流程。 WebSocket系列下一篇文章將會介紹在線上環境中,如何保證WebSocket的鏈接,以及線上可能遇到的問題。經過應對WebSocket可能出現的問題,咱們可以讓整個長鏈接更加健壯。

相關文章
相關標籤/搜索