simpleproto 是一个 TCP 简单传输协议

发布于 2021-11-25 22:46:29 字数 3097 浏览 1233 评论 0

在 Socket(TCP)连接中传输数据,如果不对数据包做特殊处理,可能出现如下所谓的粘包、拆包的问题:

// 发送方发送一个数据
sender.write(data);

// 接收方通过以下方式接收的数据和发送的不一致
receiver.on('data', (data) => {
  console.log(data);
})

simpleproto 通过对传输及接收的数据简单组包及解包解决上述问题:

// 发送方
const { encode } = require('simpleproto');
/**
 * 包的格式
 * --------------------------------
 * 1B  |  4B  | length  | 1B
 * 0x2 | length | message | 0x5
 * --------------------------------
 */
sender.write(encode(data));

// 接收方
const { decode } = require('simpleproto'); 

decode(receiver, (data) => {
  // 获取发送过来的数据的buffer对象
  console.log(data);
});

安装

npm i --save simpleproto

使用

启动一个 socket server 服务:

// server.js
const net = require('net');
const { encode, decode } = require('simpleproto');

const noop = _ => _;
const server = net.createServer((socket) => {
    socket.on('error', noop);
    decode(socket, (data) => {
      data = `${data}`;
      console.log('Server receive data length:', data.length);
      socket.write(encode(data));
    });
  });
server.listen(9999, () => {
  console.log(`server listening on ${server.address().port}.`);
});

客户端代码:

为方便查看内部数据包传输请求,采用 socketx 将请求代理到本地 whistle

const { connect } = require('socketx');
const { encode, decode } = require('simpleproto');

(async () => {
  const proxy = {
    host: '127.0.0.1',
    port: 8899,
  };
  const client = await connect({
    host: '127.0.0.1',
    port: 9999,
    proxy,
  });
  decode(client, (data) => {
    console.log('Client receive data length:', `${data}`.length);
  });
  client.on('error', (e) => console.error(e));
  setInterval(() => {
    const data = 'test123456'.repeat(1024 * 3);
    console.log('send data length:', data.length);
    client.write(encode(data));
  }, 3000);
})();

从运行结果及 whistle 抓包可以看成,客户端发送 30k 数据后,socket 连接虽然把这些数据拆成几个包,而通过 simpleproto 在客户端及服务端都可以正确的获取完整的数据包。

API

const { encode, decode, Decoder } = require('simpleproto');

encode(data)

对数据进行组包,data 可以为 buffer、string、object

decode(stream, cb)

stream 为数据流(socket、文件流等),每次接收到新的数据包都会触发 cb(data)

new Decoder([stream[, cb]])

解包类对象,构造方法可以传入 streamcb ,功能同 decode(stream, cb);也可以用于解包非数据流的字节码:

const decoder = new Decoder();
decoder.onData = (data) => {
  console.log(data);
};
decoder.write(buf);

项目地址:https://github.com/avwo/simpleproto

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84960 人气
更多

推荐作者

漫雪独思

文章 0 评论 0

垂暮老矣

文章 0 评论 0

鹊巢

文章 0 评论 0

萌酱

文章 0 评论 0

雨说

文章 0 评论 0

冰葑

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文