摘要:涉及到計(jì)算機(jī)基礎(chǔ)知識,例如字節(jié)緩沖大小端等。是指用多少位表示的整數(shù),例如就是用位即一個(gè)字節(jié)表示的整數(shù),二進(jìn)制范圍是,對應(yīng)的十進(jìn)制就是。開發(fā)時(shí)通訊雙方或者多方終端都遵循協(xié)議。
這里記錄了使用 protobuf 協(xié)議與服務(wù)端數(shù)據(jù)交互的相關(guān)內(nèi)容和知識。字節(jié) / Byte涉及到計(jì)算機(jī)基礎(chǔ)知識,例如字節(jié)、buffer 緩沖、大小端等。
1 字節(jié)代表了 8 位(bit)二進(jìn)制,1 位就是 0 或 1,也是計(jì)算機(jī)最小單位。
Uint 與 IntInt 是帶正負(fù)號的整數(shù),Uint 是從 0 開始計(jì)的整數(shù)。
Uintx 是指用多少位表示的整數(shù),例如 Uint8 就是用 8位(即一個(gè)字節(jié)) 表示的整數(shù),二進(jìn)制范圍是 00000000 ~ 11111111,對應(yīng)的十進(jìn)制就是 0 ~ 255。
但是人類的數(shù)學(xué)里面負(fù)數(shù),所以 Int8 就描述了包含負(fù)數(shù)在內(nèi)的整數(shù)范圍,即十進(jìn)制的 -128 ~ 127
更多描述如下所示
Uint8 -- (0 to 2^8 - 1) Int8 -- (-2^7 to +2^7 - 1) Uint16 -- (0 to 2^16 - 1) Int16 -- (-2^15 to +2^15 - 1) Uint32 -- (0 to 2^32 - 1) Int32 -- (-2^31 to +2^31) Uint64 -- (0 to 2^64 - 1) Int64 -- (-2^63 to +2^63 - 1)ArrayBuffer
ArrayBuffer?對象用來表示通用的、固定長度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)。參考MDN
// 以下為創(chuàng)建 12 個(gè)字節(jié)的 buffer 的例子 const buffer = new ArrayBuffer(12);
上面的操作代表向操作系統(tǒng)申請了 12 字節(jié)的二進(jìn)制緩沖,大概如下分布
| 00000000 | 00000000 | 00000000 | 00000000 | ...(還有8字節(jié))
ArrayBuffer 對象并不能直接被操作,需要通過 TypedArray 對象實(shí)例或者 DataView 實(shí)例作為橋梁來操作。
// Uint8Array 的單位為一字節(jié)與 ArrayBuffer 的基本單位吻合 const uint8 = new Uint8Array(buffer); console.log(uint0) // 輸出 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] uint8[0] = 12; // 此時(shí) buffer 變成 [12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
TypedArray 對象一覽 MDN
類型 | 大小(字節(jié)單位) | 描述 | Web IDL type | |
---|---|---|---|---|
Int8Array | 1 | 8位二進(jìn)制帶符號整數(shù) -2^7~(2^7) - 1 | byte | |
Uint8Array | 1 | 8位無符號整數(shù) 0~(2^8) - 1 | octet | |
Int16Array | 2 | 16位二進(jìn)制帶符號整數(shù) -2^15~(2^15)-1 | short | |
Uint16Array | 2 | 16位無符號整數(shù) 0~(2^16) - 1 | unsigned short | |
Int32Array | 4 | 32位二進(jìn)制帶符號整數(shù) -2^31~(2^31)-1 | long | |
Uint32Array | 4 | 32位無符號整數(shù) 0~(2^32) - 1 | unsigned int | |
Float32Array | 4 | 32位IEEE浮點(diǎn)數(shù) | unrestricted | float |
Float64Array | 8 | 64位IEEE浮點(diǎn)數(shù) | unrestricted | double |
除了 TypedArray,還可以通過 DataView 來做更細(xì)致的操作
例如我們需要在特定字節(jié)段內(nèi)寫入對應(yīng)的數(shù)據(jù)
| DataLen 4 個(gè)字節(jié) | SessionID 8 個(gè)字節(jié) | ...
const view = new DataView(buffer); const DataLen = 100; // buffer 數(shù)據(jù)總長度 const SessionID = 123456789; // SessionID // 最后的參數(shù)為大小端排序 view.setUint32(0, DataLen, true); view.setBigUint64(4, BigInt(SessionID), true);
讀取內(nèi)容
const view = new DataView(buffer); // 讀取小端字符順序 const DataLen = view.getUint32(0, true); const SessionID = view.getBigUint64(4, true);
什么是大小端
Little-Endian就是低位字節(jié)排放在內(nèi)存的低地址端,高位字節(jié)排放在內(nèi)存的高地址端。
Big-Endian就是高位字節(jié)排放在內(nèi)存的低地址端,低位字節(jié)排放在內(nèi)存的高地址端。
更多詳情參考維基百科的字節(jié)順序
JS 的大數(shù)處理JS 并不能處理 Int64 精度的數(shù),所以在 stage 3 引入了 BigInt API,解決大數(shù)精度問題,Chrome 和 Firefox 已經(jīng)支持,但是 Safari 并不支持,需要用另外的辦法處理。
兼容方式參考 這里
Protobuf 應(yīng)用Google Protocol Buffers 是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化,或者說序列化。
開發(fā)時(shí)通訊雙方或者多方終端都遵循 proto 協(xié)議。
然后看看前端如何使用 protobuf
Google 官方的庫對 JS 支持不是太友好,這里我們使用 protobuf.js 庫
創(chuàng)建一個(gè) sdk.proto 文件
syntax = "proto3"; package yourPackage; message LoginReq { string UserName = 1; string Password = 2; }
yarn add protobufjs -D # 使用 protobufjs 提供的 Command line pbjs ./sdk.proto -t static-module > ./sdk.js # 生成 ts 聲明文件 pbts -o ./sdk.d.ts ./sdk.js
生成好文件即可使用
import SDK from "./sdk"; const { LoginReq } = SDK.yourPackage; const payload = { UserName: "alex", Password: "123" } const message = LoginReq.create(payload); // or use .fromObject if conversion is necessary // encode 信息 const protoBuffer = LoginReq.encode(message).finish(); // 把 protobuf buffer 寫入到上面的 SessionID buffer 信息中 const uint8 = new Uint8Array(buffer); uint8.set(protoBuffer, offset) // 使用 websocket 發(fā)送 arrayBuffer 數(shù)據(jù) const socket = new WebSocket(host) socket.onopen = () => { socket.send(protoBuffer) } socket.onmessage = () => { // decode operator }總結(jié)
這里只是簡單的記錄過程,如果想要更多細(xì)節(jié)的信息,可以參考 little-chat 的源碼
參考
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106373.html
摘要:原文地址帶入及相關(guān)介紹項(xiàng)目地址作為開篇章,將會(huì)介紹相關(guān)的一些知識。 原文地址:帶入gRPC:gRPC及相關(guān)介紹 項(xiàng)目地址:go-grpc-example 作為開篇章,將會(huì)介紹 gRPC 相關(guān)的一些知識。簡單來講 gRPC 是一個(gè) 基于 HTTP/2 協(xié)議設(shè)計(jì)的 RPC 框架,它采用了 Protobuf 作為 IDL 你是否有過疑惑,它們都是些什么?本文將會(huì)介紹一些常用的知識和概念,更詳...
摘要:帶入及相關(guān)介紹原文地址帶入及相關(guān)介紹項(xiàng)目地址作為開篇章,將會(huì)介紹相關(guān)的一些知識。 帶入gRPC:gRPC及相關(guān)介紹 原文地址:帶入gRPC:gRPC及相關(guān)介紹 項(xiàng)目地址:go-grpc-example 作為開篇章,將會(huì)介紹 gRPC 相關(guān)的一些知識。簡單來講 gRPC 是一個(gè) 基于 HTTP/2 協(xié)議設(shè)計(jì)的 RPC 框架,它采用了 Protobuf 作為 IDL 你是否有過疑惑,它們都...
摘要:結(jié)構(gòu)作為服務(wù)端作為序列化數(shù)據(jù)的協(xié)議前端通訊演示地址服務(wù)端實(shí)現(xiàn)啟動(dòng)類長連接示例主線程組從線程組請求的解碼和編碼把多個(gè)消息轉(zhuǎn)換為一個(gè)單一的或是,原因是解碼器會(huì)在每個(gè)消息中生成多個(gè)消息對象主要用于處理大數(shù)據(jù)流,比如一個(gè)大小的文件如果你直接傳輸肯定 結(jié)構(gòu) netty 作為服務(wù)端 protobuf 作為序列化數(shù)據(jù)的協(xié)議 websocket 前端通訊 演示 GitHub 地址 showImg(...
摘要:結(jié)構(gòu)作為服務(wù)端作為序列化數(shù)據(jù)的協(xié)議前端通訊演示地址服務(wù)端實(shí)現(xiàn)啟動(dòng)類長連接示例主線程組從線程組請求的解碼和編碼把多個(gè)消息轉(zhuǎn)換為一個(gè)單一的或是,原因是解碼器會(huì)在每個(gè)消息中生成多個(gè)消息對象主要用于處理大數(shù)據(jù)流,比如一個(gè)大小的文件如果你直接傳輸肯定 結(jié)構(gòu) netty 作為服務(wù)端 protobuf 作為序列化數(shù)據(jù)的協(xié)議 websocket 前端通訊 演示 GitHub 地址 showImg(...
閱讀 1848·2021-08-19 11:12
閱讀 1425·2021-07-25 21:37
閱讀 988·2019-08-30 14:07
閱讀 1267·2019-08-30 13:12
閱讀 651·2019-08-30 11:00
閱讀 3529·2019-08-29 16:28
閱讀 990·2019-08-29 15:33
閱讀 2966·2019-08-26 13:40