• 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
    
    • 1

    3. 编写 .proto 文件

    // 举例:user_login.proto
    
    syntax = "proto3";
    package user;
    
    message UserInfoRequest {
        int64 userId = 1;
    }
    
    message UserInfoResponse {
        int32 userType = 1;
        string mobile = 2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    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
            )
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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' }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    ImportError: cannot import name ‘TouchActions‘ from ‘selenium.webdriver‘
    E1696 无法打开 源 文件 “string.h“
    Ubuntu20.04安装graph-tool
    MySQL 性能监控
    vue3.2的发布的release.js源码
    在线打印资料的软件叫什么名字来着
    SpringCloud(34):Nacos服务发现
    winlicense官方版是一款功能专业强大的编程软件
    极智嘉(Geek+)官宣重磅合作伙伴,再度赋能仓储自动化解决方案落地
    Web Scraping指南: 使用Selenium和BeautifulSoup
  • 原文地址:https://blog.csdn.net/think_A_lot/article/details/126765780