Javascript基于protobufjs接入protobuf

文章转载自我自己的小破站,欢迎大佬们进来瞧一瞧

1. Google Protocol Buffer

Google Protocol Buffer(简称 Protobuf)是 Google 公司内部的混合语言数据标准。Protobuf 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前以支持十多种主流编程语言。

官方技术文档 https://developers.google.com/protocol-buffers

2. 安装 protobufjs

protobufjs GitHub仓库,前端直接使用 npm 安装即可。

npm install protobufjs

3. 编写 .proto 文件

// 举例:user_login.proto

syntax = "proto3";
package user;

message UserInfoRequest {
    int64 userId = 1;
}

message UserInfoResponse {
    int32 userType = 1;
    string mobile = 2;
}

4. protobufjs 加载 .proto 文件

// 从protobufjs中引入加载器
import { load } from 'protobufjs';

// 加载user_login.proto并解析
load('user_login.proto', (err, root) => {
  if (err) {
    return;
  }
  // Obtain a message type
  const UserInfoRequest = root.lookupType('user.UserInfoRequest');

  // Exemplary payload
  const payload = {
    userId: 1
  }

  // Verify the payload if necessary (i.e. when possibly incomplete or invalid)
  const errMsg = UserInfoRequest.verify(payload);
  if (errMsg) {
    console.error(errMsg);
    return;
  }
  // Create a new message
  var message = UserInfoRequest.create(payload); // or use .fromObject if conversion is necessary
  // Encode a message to an Uint8Array (browser) or Buffer (node)
  var messageBuffer = UserInfoRequest.encode(message).finish();

  // do something with messageBuffer
})

5. 消息发送

这时候如果将上文解析得到的 messageBuffer 直接通过 http 请求发送出去,服务端会报下面这个错误。这说明数据在服务器侧解析的过程中出了些问题,格式没对应上。

com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero);

仔细观察上述代码,可以发现 UserInfoRequest.encode 之后拿到的二进制数据格式是 Uint8Array,但是 protobuf 使用的二进制数据格式是 ArrayBuffer,二者并没有对应上。于是,我们需要在发送前将 Uint8Array 转换为 ArrayBuffer。具体的代码如下:

axios.create({
  url: '/hello',
  method: 'post',
  headers: {
    'Content-Type': "application/x-protobuf"
  },
  responseType: 'arraybuffer',
  // https://stackoverflow.com/questions/37228285/uint8array-to-arraybuffer
  data: messageBuffer.buffer.slice(
          messageBuffer.byteOffset,
          messageBuffer.byteOffset + messageBuffer.byteLength
        )
})

6. 消息接收

同样的,服务器返回的编码格式是 ArrayBuffer,需要先转化为 Uint8Array,再使用 protobufjs 解析,对应的报文格式定义在 UserInfoResponse 。

// axios返回内容
const res = response.data;

load('user_login.proto', (err, root) => {
  const UserInfoResponse = root.lookupType('user.UserInfoResponse');
  var message = UserInfoResponse.decode(new Uint8Array(res));
  var object = UserInfoResponse.toObject(message, {
      longs: String,
      enums: String,
      bytes: String,
      // see ConversionOptions
  });
  console.log(object);
  // 输出形如 { userType: 1234, mobile: 'xxx' }
})
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZTao-z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值