技术文章 > 服务端 > pomelo-protobuf 

Pomelo-protobuf

Pomelo-protobuf 协议是一种高效的二进制数据编码协议模块,该模块在 pomelo 中实现 protobuf 协议用于数据传输。当然,Pomelo-protobuf 也可以在其他项目中独立使用。
与谷歌 protobuf 不同的是,我们在 pomelo-protobuf 中提供了一个通用的编码器和解码器。我们使用 protos 文件作为元数据来编码/解码消息,因此您不需要向项目添加任何代码,相应的,您需要添加一个protos.json(或两个,用于不同的编码器和解码器消息)文件来定义需要通过 protobuf 编码的消息。pomelo-protobuf 的结构如下:

用法


定义 protos

要使用 pomelo-protobuf,需要编写一个 json 文件来定义消息格式。该文件的语法与 protobuf 中的 .proto 文件相同,但使用 json 格式表示,protos.json 示例如下 :
{
  "onMove" : {
    "required uInt32 entityId" : 1,
    "message Path": {
      "required uInt32 x" : 1,
      "required uInt32 y" : 2
    },
    "repeated Path path" : 2,
    "required uInt32 speed" : 3
  },
  "onAttack" : {
    "required uInt32 attacker" : 1,
    "required uInt32 target" : 2,
    "message AttackResult" : {
      "required uInt32 result" :  1,
      "required uInt32 damage" : 2,
      "optional uInt32 exp" : 3
    },
    "required AttackResult result" : 3
  }
}
与 google protobuf 不同,我们将所有 proto 都写在同一个文件中,并使用一个唯一的键来定义消息。
要使用 protos,我们使用解析器将 protos 文件解析为对机器更友好的格式,即 json 格式,然后您可以使用结果来解码/编码消息。

RootMessage 支持

您可以在 protos 中编写 RootMessage 以供全局使用。
{
  "message Path": {
    "required double x" : 1,
    "required double y" : 2
  },
  "message Equipment" : {
    "required uInt32 entityId" : 1,
    "required uInt32 kindId" : 2
  },
  "onMove" : {
    "required uInt32 entityId" : 1,
    "repeated Path path" : 2,
    "required float speed" : 3
  },
  "area.playerHandler.enterScene" : {
    "message Player" : {
      "message Bag" : {
        "message Item" : {
          "required uInt32 id" : 1,
          "optional string type" : 2
        },
        "repeated Item items" : 1
      },
      "required uInt32 entityId" : 1,
      "required uInt32 kindId" : 2,
      "required Bag bag" : 3,
      "repeated Equipment equipments" : 4
    },
    "optional Player curPlayer" : 2
  }
}

服务端和客户端

Pomelo protobuf 有 js 的服务器代码和客户端代码。
服务端代码运行在 Node.JS 环境中,使用缓冲器(Buffer)表示二进制数据。
客户端代码在浏览器上运行,使用字节数组(ByteArray)来表示二进制数据。
平均而言,服务器版本的编码/解码速度比客户端版本快 60%,内存使用量更少。因此,我们强烈建议使用 Node.JS 上的服务器代码以获得更好的性能。
样例消息 protos.json:
var key = 'onMove';
var msg = {
  entityId : 14,
  path : [{x : 128,y : 796},{x : 677,y : 895}],
  speed : 160
};
服务端编/解码
//Require proto buf module
var protobuf = require('protobuf');

//Set encode protos and decode protos
var protos = protobuf.parse(require('./protos.json'));
protobuf.init({encoderProtos:protos, decoderProtos:protos});

//Encode msg to binary Buffer
var buffer = protobuf.encode(key, msg);

//Decode a msg from binary buffer
var decodeMsg = protobuf.decode(key, buffer);
在服务器端,编码结果将是一个Buffer。编码器原型和解码器原型可能不同,在这种情况下,我们对编码器和解码器使用相同的原型。
客户端编/解码
要在浏览器(或其他前端 js 开发工具如 cocos2dx-js)中使用 protbuf,您需要在 html(或js)文件中包含 /client/protbuf.js。
//Require proto buf
var protobuf = require('protobuf');

//Get parsed protos from server
var protos = getProtos();

//Init protobuf
protobuf.init({encoderProtos:protos, decoderProtos:protos});

//Encode msg to binary Buffer
var buffer = protobuf.encode(key, msg);

//Decode a msg from binary buffer
var decodeMsg = protobuf.decode(key, buffer);
Protobuf 将是一个全局变量,您需要从服务器获取解析后的 protos。其他的与服务器端相同,只是编码器的结果将由 ByteArray 而不是 Buffer 产生。

兼容性

对于相同的消息和 proto,pomelo protobuf 和 google protobuf 的编码结果是相同的。这意味着你可以与 google protobuf 交换二进制数据。 我们在 proto 文件中进行了一些更改,并且有一些功能我们不支持,不同之处如下:


来源:摘自 https://github.com/pomelonode/pomelo-protobuf,本站 行痴 翻译整理