protobuf.js是一款直接解析proto文件实现Protocol Buffers通讯的插件

protobuf.js是一款直接解析proto文件实现Protocol Buffers通讯的插件

protobuf.js是一个纯 JavaScript 实现,对node.js和浏览器的TypeScript 都支持。它易于使用,速度极快,开箱即用,无需本地编译proto文件,它是在线实时编译解析proto文件实现消息通讯。

Protocol Buffers是一种语言中立、平台中立、可扩展的序列化结构化数据的方式,用于通信协议、数据存储等,最初由 Google 设计,传输高效。

安装

nodejs运行:

npm install protobufjs [--save --save-prefix=~]

var protobuf = require("protobufjs");

命令行实用程序位于 protobufjs-cli 包中,必须单独安装:

npm install protobufjs-cli [--save --save-prefix=~]

浏览器运行:

<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/protobuf.7.2.3.js"></script>

使用方式:

使用 .proto 文件

可以使用完整的库加载现有的 .proto 文件,该库解析并编译定义以准备使用(基于反射的)消息类:

// awesome.proto

package awesomepackage;
syntax = "proto3";

message AwesomeMessage {
string awesome_field = 1; // becomes awesomeField
}

js

protobuf.load("awesome.proto", function(err, root) {
if (err)
throw err;

// Obtain a message type
var AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");

// Exemplary payload
var payload = { awesomeField: "AwesomeString" };

// Verify the payload if necessary (i.e. when possibly incomplete or invalid)
var errMsg = AwesomeMessage.verify(payload);
if (errMsg)
throw Error(errMsg);

// Create a new message
var message = AwesomeMessage.create(payload); // or use .fromObject if conversion is necessary

// Encode a message to an Uint8Array (browser) or Buffer (node)
var buffer = AwesomeMessage.encode(message).finish();
// ... do something with buffer

// Decode an Uint8Array (browser) or Buffer (node) to a message
var message = AwesomeMessage.decode(buffer);
// ... do something with message

// If the application uses length-delimited buffers, there is also encodeDelimited and decodeDelimited.

// Maybe convert the message back to a plain object
var object = AwesomeMessage.toObject(message, {
longs: String,
enums: String,
bytes: String,
// see ConversionOptions
});
});


此外,如果愿意,可以通过省略回调来使用 promise 语法:

protobuf.load("awesome.proto")
.then(function(root) {
...
});
使用 JSON 描述符

该库使用等同于 .proto 定义的 JSON 描述符。例如,以下内容与上面看到的 .proto 定义相同:

// awesome.json

{
  "nested": {
    "awesomepackage": {
      "nested": {
        "AwesomeMessage": {
          "fields": {
            "awesomeField": {
              "type": "string",
              "id": 1
            }
          }
        }
      }
    }
  }
}

详细文档地址:https://protobufjs.github.io/protobuf.js/

完整示例代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum=1.0,minimum=1.0,user-scalable=0" />
    <title>BFW NEW PAGE</title>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/protobuf.7.2.3.js"></script>
    <script type="text/javascript">
      var protoRoot = null;
protobuf.load('/asset/user.proto', function(err, root) {
    if (err)
        throw err;
    protoRoot = root;
    
    // Obtain a message type
    var AwesomeMessage = root.lookupType("User");

    // Exemplary payload
    var payload = { name: "第三方" };

    // Verify the payload if necessary (i.e. when possibly incomplete or invalid)
    var errMsg = AwesomeMessage.verify(payload);
    if (errMsg)
        throw Error(errMsg);

    // Create a new message
    var message = AwesomeMessage.create(payload); // or use .fromObject if conversion is necessary

    // Encode a message to an Uint8Array (browser) or Buffer (node)
    var buffer = AwesomeMessage.encode(message).finish();
    
    


var xhr = new XMLHttpRequest();  
xhr.open('POST', 'your.php');
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.send(buffer);
    // ... do something with buffer
});


function writeBuf(msgid, buf) {
    // buf 是protobuf消息的二进制结果
    var length = buf.length;
    var buffer = new ArrayBuffer(buf.length + 4); // 消息ID占4位
    var dv = new DataView(buffer);
    dv.setUint32(0, msgid, false); // 大端字节序
    for (let i=0;i<buf.length;i++) {
        dv.setInt8(4+i, buf[i]); // 逐字节写入buffer
    }
    console.log(buffer);
    return buffer;
}
function readBuf(buf) {
    var dv = new DataView(buf);
    var msgid = dv.getUint32(0, false);
    var buf = new Uint8Array(buf, 4); // 截取消息ID后面的字节,交给protobuf解析
    return [msgid, buf];
}
function Request_Message(msg, req, callback) {
    // 将客户端请求的消息msg转成protobuf 
    var RequestMessage = protoRoot.lookupType("dapianzi."+req); // 这里需要加上命名空间
    var errMsg = RequestMessage.verify(msg);
    if (errMsg)
        throw Error(errMsg);
    var message = RequestMessage.fromObject(msg);
    var buffer = RequestMessage.encode(message).finish();
    callback(buffer); // 下一步调用writeBuf 产生消息包,发送给服务器
}
function Response_Message(buf, res, callback) {
    // buf 是readBuf()中返回的二进制串,这里交给protobuf解析成消息体
    var ResponseMessage = protoRoot.lookupType("dapianzi."+res);
    var message = ResponseMessage.decode(buf);
    var object = ResponseMessage.toObject(message, {
        longs: String,
        enums: String,
        bytes: String,
    });
    callback(object); // 进行客户端逻辑
}

    </script>
     <style>
      </style>
</head>
<body>

</body>
</html>
		


立即下载protobuf.7.2.3.js查看所有js插件

网友评论0

程序员在线工具箱