摘要:本文作為系列的第四篇內(nèi)容,將會(huì)用一個(gè)簡(jiǎn)單的聊天應(yīng)用把整個(gè)傳輸二進(jìn)制數(shù)據(jù)類型的內(nèi)容連接起來(lái),讓用戶對(duì)整個(gè)傳輸二進(jìn)制數(shù)據(jù)的方法有個(gè)了解。如何發(fā)送二進(jìn)制數(shù)據(jù)通過(guò)如何設(shè)計(jì)一個(gè)二進(jìn)制協(xié)議一章,我們知道了如何定義傳輸?shù)亩M(jìn)制數(shù)據(jù)格式。
概述
通過(guò)前三篇博客,我們能夠了解在通過(guò)WebSocket發(fā)送數(shù)據(jù)之前,我們需要傳遞的數(shù)據(jù)是如何變成ArrayBuffer二進(jìn)制數(shù)據(jù)的;在我們收到二進(jìn)制數(shù)據(jù)之后,我們又如何將其變成了JavaScript中的常見(jiàn)數(shù)據(jù)類型。
本文作為WebSocket系列的第四篇內(nèi)容,將會(huì)用一個(gè)簡(jiǎn)單的IM聊天應(yīng)用把整個(gè)WebSocket傳輸二進(jìn)制數(shù)據(jù)類型的內(nèi)容連接起來(lái),讓用戶對(duì)整個(gè)WebSocket傳輸二進(jìn)制數(shù)據(jù)的方法有個(gè)了解。
本文的主要內(nèi)容如下:
如何設(shè)計(jì)一個(gè)二進(jìn)制協(xié)議
WebSocket如何發(fā)送二進(jìn)制數(shù)據(jù)
WebSocket如何處理接收的二進(jìn)制數(shù)據(jù)
之前的博客我們介紹過(guò)了WebSocket基礎(chǔ)知識(shí),數(shù)字類型和字符串類型與二進(jìn)制數(shù)據(jù)間的轉(zhuǎn)換,如果沒(méi)有相關(guān)的基礎(chǔ),建議先依次閱讀以下文章:
WebSocket系列之基礎(chǔ)知識(shí)入門篇
WebSocket系列之JavaScript中數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)
WebSocket系列之字符串如何與二進(jìn)制數(shù)據(jù)進(jìn)行轉(zhuǎn)換
如何設(shè)計(jì)一個(gè)二進(jìn)制協(xié)議 什么是協(xié)議協(xié)議,網(wǎng)絡(luò)協(xié)議的簡(jiǎn)稱,網(wǎng)絡(luò)協(xié)議是通信計(jì)算機(jī)雙方必須共同遵從的一組約定。如怎么樣建立連接、怎么樣互相識(shí)別等。只有遵守這個(gè)約定,計(jì)算機(jī)之間才能相互通信交流。它的三要素是:語(yǔ)法、語(yǔ)義、時(shí)序。
通過(guò)百度百科中的介紹,我們對(duì)協(xié)議的概念有了一個(gè)基礎(chǔ)的了解。通俗來(lái)說(shuō),協(xié)議就是通信雙方約定好的一套規(guī)則。
為什么要設(shè)計(jì)協(xié)議沒(méi)有規(guī)矩不成方圓。通信雙方只有通過(guò)協(xié)議,才能夠識(shí)別對(duì)方發(fā)送的數(shù)據(jù)內(nèi)容。
我們應(yīng)該如何設(shè)計(jì)這套協(xié)議首先,協(xié)議的設(shè)計(jì)應(yīng)該能夠區(qū)分不同的各個(gè)數(shù)據(jù)包;其次,它還需要具備一定的兼容性。
根據(jù)上述兩點(diǎn)要求,我們?cè)O(shè)計(jì)了一套簡(jiǎn)單的IM聊天協(xié)議,支持文本、圖片、文件三種消息。這套協(xié)議是按照最簡(jiǎn)單的思路來(lái)設(shè)計(jì)的,因此也只是給大家一個(gè)參考的觀點(diǎn),在真正的線上使用場(chǎng)景中,協(xié)議會(huì)比本文中的復(fù)雜和更加有層次。具體格式如下:
{ "id": "short", // 消息類型,1是文本協(xié)議格式;2是圖片協(xié)議格式;3是文件協(xié)議格式 "sender": "long", // 發(fā)送用戶唯一id "reciever": "long", // 接受用戶唯一id "data": "string" // 消息內(nèi)容,如果是文本協(xié)議則為文本內(nèi)容;如果是圖片協(xié)議則為圖片地址;如果是文件協(xié)議則為文件地址 }這套協(xié)議如何使用 發(fā)送消息
從協(xié)議格式可知,將上述數(shù)據(jù)按照上述固定順序放入ArrayBuffer中,即可得到一個(gè)有特定含義的二進(jìn)制數(shù)據(jù)。例如:
{ "id": 1, "sender": "123", "reciever": "456", "data": "Hellow World" }
當(dāng)我們需要發(fā)送此消息時(shí),只需要:
在前2個(gè)Byte放入id。
接下來(lái)8個(gè)Byte中放入sender。
再接下來(lái)8個(gè)Byte放入reciever。
最后緊接著放入一個(gè)string類型(以WebSocket系列之字符串如何與二進(jìn)制數(shù)據(jù)進(jìn)行轉(zhuǎn)換博客中的格式為例,先將字符串長(zhǎng)度構(gòu)造成一個(gè)int類型,放在前4個(gè)Byte中,接下來(lái)將string類型編碼后放入)。
此數(shù)據(jù)就完全按照協(xié)議構(gòu)造完成了。我們只需將次協(xié)議通過(guò)WebSocket發(fā)送即可。具體方法將會(huì)在后面章節(jié)中說(shuō)明。
接收消息從協(xié)議格式可知,當(dāng)我們收到一條消息時(shí),只需要按照協(xié)議規(guī)范來(lái)進(jìn)行反向解析即可。例如:
{ "id": 1, "sender": "123", "reciever": "456", "data": "Hellow World" }
如果發(fā)送端發(fā)送的數(shù)據(jù)仍然為此消息,我們的解析順序?yàn)椋?/p>
先根據(jù)前2個(gè)Byte讀取一個(gè)Short類型的id數(shù)值。
將接下來(lái)的8個(gè)Byte讀取為L(zhǎng)ong類型的sender字段。
再接下來(lái)的8個(gè)Byte讀取為L(zhǎng)ong類型的reciever字段。
接下來(lái)讀取一個(gè)string類型(以發(fā)送消息這一節(jié)的數(shù)據(jù)為例,先讀取4個(gè)Byte長(zhǎng)度的int類型字符串長(zhǎng)度,然后再根據(jù)長(zhǎng)度讀取字符串即可)。
擴(kuò)展此協(xié)議當(dāng)此協(xié)議字段無(wú)法滿足并且已經(jīng)在線上使用時(shí),我們應(yīng)該如何擴(kuò)展呢?
根據(jù)我們的寫入和讀取步驟,我們可以知道:每次我們讀取的二進(jìn)制數(shù)據(jù)可以認(rèn)為是一個(gè)格式固定的數(shù)據(jù)(string類型在構(gòu)造時(shí)會(huì)有長(zhǎng)度信息,因此認(rèn)為也是長(zhǎng)度相對(duì)固定),所以我們?cè)谧x取二進(jìn)制數(shù)據(jù)時(shí)讀取的長(zhǎng)度也是固定的。因此,我們?cè)跀U(kuò)展時(shí)只需要往協(xié)議后面增加字段即可。
擴(kuò)展前的應(yīng)用仍然會(huì)讀取之前已經(jīng)確定的數(shù)據(jù)協(xié)議,只需要保證內(nèi)容不變,那么功能也不會(huì)變。
擴(kuò)展后的應(yīng)用能夠解析擴(kuò)展后的協(xié)議,因此得到更多的數(shù)據(jù),從而可以實(shí)現(xiàn)更多的功能。
WebSocket如何發(fā)送二進(jìn)制數(shù)據(jù)通過(guò)如何設(shè)計(jì)一個(gè)二進(jìn)制協(xié)議一章,我們知道了如何定義WebSocket傳輸?shù)亩M(jìn)制數(shù)據(jù)格式。下面,我們來(lái)看下如何在WebSocket中發(fā)送二進(jìn)制數(shù)據(jù):
let arrayBuffer = getArrayBufferMessagesFromUser(); // 獲取用戶需要發(fā)送的消息數(shù)據(jù),為一個(gè)ArrayBuffer對(duì)象 let webSocket = getWebSocket(); // 獲取已經(jīng)連接成功的WebSocket實(shí)例 websocket.binaryType = "arraybuffer"; // 指定WebSocket接受ArrayBuffer實(shí)例作為參數(shù) webSocket.send(arrayBuffer);
通過(guò)上面的示例我們可以知道,WebSocket在發(fā)送string類型的數(shù)據(jù)或者ArrayBuffer類型的數(shù)據(jù)時(shí),使用的API接口都是send方法,我們只需要在WebSocket初始化后指定傳輸類型binaryType即可。
WebSocket如何處理接收的二進(jìn)制數(shù)據(jù)通過(guò)WebSocket如何發(fā)送二進(jìn)制數(shù)據(jù)一章,我們知道了如何發(fā)送二進(jìn)制數(shù)據(jù)。接下來(lái),讓我們開看下如何處理WebSocket接收到的二進(jìn)制數(shù)據(jù):
let webSocket = getWebSocket(); // 獲取已經(jīng)連接成功的WebSocket實(shí)例 websocket.binaryType = "arraybuffer"; // 指定WebSocket接受ArrayBuffer實(shí)例作為參數(shù) webSocket.addEventListener("message", (message) => { let arrayBuffer = message.data; // 獲取用戶接收到的消息數(shù)據(jù),為一個(gè)ArrayBuffer對(duì)象 let data = parseMessage(arrayBuffer); // 解析二進(jìn)制數(shù)據(jù) });
通過(guò)上面的示例我們可以知道,當(dāng)我們?cè)诮⑦B接時(shí)指定了傳輸類型binaryType為ArrayBuffer之后,我們通過(guò)WebSocket收到的數(shù)據(jù)也是一個(gè)ArrayBuffer實(shí)例。我們只需要根據(jù)第一章講解的方式進(jìn)行解析即可。
總結(jié)本文作為WebSocket系列的第四篇,通過(guò)一個(gè)IM聊天應(yīng)用的示例將前三篇博客分享的內(nèi)容串聯(lián)起來(lái),給讀者完整介紹了在WebSocket中使用二進(jìn)制數(shù)據(jù)進(jìn)行傳輸?shù)姆椒ㄒ约跋嚓P(guān)的數(shù)據(jù)類型轉(zhuǎn)換。
通過(guò)前面4篇博客的內(nèi)容,讀者可以根據(jù)自己的需求快速的構(gòu)造和封裝WebSocket進(jìn)行二進(jìn)制數(shù)據(jù)傳輸,基本能夠串聯(lián)整個(gè)應(yīng)用流程。
WebSocket系列下一篇文章將會(huì)介紹在線上環(huán)境中,如何保證WebSocket的連接,以及線上可能遇到的問(wèn)題。通過(guò)應(yīng)對(duì)WebSocket可能出現(xiàn)的問(wèn)題,我們能夠讓整個(gè)長(zhǎng)連接更加健壯。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/93869.html
摘要:與此同時(shí),后端服務(wù)的中也有相關(guān)的長(zhǎng)連接維持時(shí)長(zhǎng)設(shè)置。如何快速的恢復(fù)連接根據(jù)上面的操作方案,我們會(huì)在網(wǎng)絡(luò)異常時(shí)斷開連接。 概述 通過(guò)前四篇博客,相信讀者對(duì)于WebSocket的使用和數(shù)據(jù)(不論是ArrayBuffer還是String)傳輸都有了一個(gè)深刻的了解。現(xiàn)在我們來(lái)介紹下,我在使用WebSocket時(shí),連接相關(guān)模塊遇到的一些共性問(wèn)題,以及我們?nèi)绾谓鉀Q這些問(wèn)題。 本文作為WebSock...
摘要:總結(jié)通過(guò)使用和,我們能夠在數(shù)據(jù)和二進(jìn)制數(shù)據(jù)中進(jìn)行互相轉(zhuǎn)換。下一篇系列相關(guān)的博客,將會(huì)介紹如何通過(guò)來(lái)向后端傳遞二進(jìn)制數(shù)據(jù),以及如何處理通過(guò)收到的二進(jìn)制數(shù)據(jù)。 概述 上一篇博客我們說(shuō)到了如何進(jìn)行數(shù)字類型(如Short、Int、Long類型)如何在JavaScript中進(jìn)行二進(jìn)制轉(zhuǎn)換,如果感興趣的可以可以閱讀本系列第二篇博客——WebSocket系列之JavaScript中數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為...
摘要:以和為例,說(shuō)明中的數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)。對(duì)象用來(lái)表示通用的固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)。中的數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)對(duì)和有了一個(gè)大概的了解,下面讓我們來(lái)看下它是如何進(jìn)行二進(jìn)制數(shù)據(jù)操作的。 概述 本文主要通過(guò)對(duì)JavaScript中數(shù)字?jǐn)?shù)據(jù)與二進(jìn)制數(shù)據(jù)之間的轉(zhuǎn)換,讓讀者能夠了解在JavaScript中如何對(duì)數(shù)字類型(包括但不限于Number類型)進(jìn)行處理。 二進(jìn)制數(shù)據(jù)在日常...
摘要:幀協(xié)議讓我們深入了解下幀協(xié)議。目前可用的值該幀接續(xù)前面一幀的有效載荷。該幀包含二進(jìn)制數(shù)據(jù)。幀有以下幾類長(zhǎng)度表示有效載荷的長(zhǎng)度。數(shù)據(jù)分片有效載荷數(shù)據(jù)可以被分成多個(gè)獨(dú)立的幀。接收端會(huì)緩沖這些幀直到位有值。 原文請(qǐng)查閱這里,略有改動(dòng),本文采用知識(shí)共享署名 3.0 中國(guó)大陸許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原...
摘要:概述本文是系列的第一篇,主要介紹相關(guān)的基礎(chǔ)協(xié)議知識(shí)和。客戶端收到響應(yīng)后,立即發(fā)起下一次的請(qǐng)求。收到消息通過(guò)事件來(lái)接收消息。類型則需要傳遞一個(gè)對(duì)象作為參數(shù),相關(guān)的內(nèi)容也將在本系列第二篇中進(jìn)行介紹。 概述 本文是WebSocket系列的第一篇,主要介紹WebSocket相關(guān)的基礎(chǔ)協(xié)議知識(shí)和API。由于WebSocket的相關(guān)介紹在MDN中分布較亂,初學(xué)者不太容易入門,因此通過(guò)本文將相關(guān)基礎(chǔ)...
閱讀 2294·2021-11-10 11:35
閱讀 912·2021-09-26 09:55
閱讀 2405·2021-09-22 15:22
閱讀 2327·2021-09-22 15:17
閱讀 3697·2021-09-09 09:33
閱讀 1834·2019-08-30 11:22
閱讀 976·2019-08-30 10:57
閱讀 649·2019-08-29 16:10