安裝
npm i @lvgithub/stick
背景
由于 TCP 協(xié)議是面向流的協(xié)議,我們使用 TCP 通信的時候,需要解析出我們的數(shù)據(jù),就需要對流進行解析。也就是所謂的拆包,把流解析為一段段我們所需要的數(shù)據(jù)。本方案為 Node.Js 實現(xiàn)的一個粘包處理方案。喜歡的話 star,想訂閱點 watch~
原理
對要發(fā)送的數(shù)據(jù)進行協(xié)議編碼,把一份數(shù)據(jù)data分為 header +body兩個結(jié)構(gòu),header 默認(rèn)固定長度(2 byte),header的內(nèi)容描述的是 body 數(shù)據(jù)的長度。由于header定長,因此可以通過解析header,動態(tài)解析 body 的內(nèi)容。
默認(rèn) header 我們使用 2 Byte 的存儲空間,即Int16最大表示的 body 長度為 32767,也就是16M。

image-20200704170816148.png
如上圖,我們看先取出數(shù)據(jù)流的前兩位,讀取到內(nèi)容 0x00, 0x02轉(zhuǎn)化為整數(shù)的長度是 2,再讀取出body第3、4位 0x61, 0x62。下面是一個簡單的demo:
// example/tcpSample.js
'use strict';
const net = require('net');
const { Stick, MaxBodyLen } = require('../index');
const stick = new Stick(1024);
// 設(shè)置最大傳輸body大小為 32K,即 header用兩個 Byte,最大表示的值為 32767
stick.setMaxBodyLen(MaxBodyLen['32K']);
// server端
const server = net.createServer(socket => {
// socket 接收到的 片段 put 到 stick 中處理
socket.on('data', data => {
stick.putData(data);
});
// stick 會解析好一個個數(shù)據(jù)包,按照接收的順序輸出
stick.onBody(body => {
console.log('body:', body.toString());
});
server.close();
});
server.listen(8080);
// client 端
const client = net.createConnection({ port: 8080, host: 'localhost' }, () => {
// 客戶端通過 stick 打包內(nèi)容
const data = stick.makeData(JSON.stringify({ userName: 'liuwei' }));
// 然后把打包對的內(nèi)容通過 TCP 發(fā)送給 服務(wù)端
client.write(data);
client.destroy();
});
Output:
$ node example/sample.js
body: {"userName":"liuwei"}
More Example
API
-
Class: Stick
-
new Stick(bufferSize: number)
Stick 類用于處理數(shù)據(jù)包,從流中解析出用戶定義的一塊快數(shù)據(jù)
- bufferSize Stick處理數(shù)據(jù)包初始化的緩存大小,默認(rèn) 512 Bytes
-
- **putData(buf: Buffer)**
往 stick 中put 收到的數(shù)據(jù)流
- **onData(callback)**
當(dāng)收到的數(shù)據(jù)流中包含了完整的數(shù)據(jù)塊,觸發(fā)回調(diào)返回數(shù)據(jù)塊(`header`+`body`)
* **callback**: (buf: Buffer): void
- **onBody(callback)**
當(dāng)收到的數(shù)據(jù)流中包含了完整的數(shù)據(jù)塊,觸發(fā)回調(diào)返回數(shù)據(jù)內(nèi)容(`body`)
- **makeData(body: string): Buffer**
用于客戶端中,幫助生成符合 Stick 協(xié)議的數(shù)據(jù)塊(`data`)
- **setMaxBodyLen(length: MaxBodyLen)**
設(shè)置`body` 的最大長度,提供兩種配置見 ** MaxBodyLen**
-
Enum: MaxBodyLen
- 32K 最大32kb
- 2048M 最大 2048M
多語言
目前數(shù)據(jù)打包方式只提供了 Node.Js 包,stick.makeData()但現(xiàn)實場景中可能很多時間,客戶端是其他語言編寫的比如C語言運行在單片機上,這時候大家可以基原理圖自行打包,規(guī)則所示:
data = header(body.length) + body