ProtoBuf.js 使用技巧
2017-08-25 10:55
761 查看
【转】http://www.maxzhang.com/2015/09/ProtoBuf-js%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/
Protocol Buffers
Protocol buffers 是一个用来序列化结构化数据的技术,支持多种语言诸如 C++、Java 以及 Python 语言,可以使用该技术来持久化数据或者序列化成网络传输的数据。相比较一些其他的 XML 技术而言,该技术的一个明显特点就是更加节省空间(以二进制流存储)、速度更快以及更加灵活。具体参见 Google 开发文档:https://developers.google.com/protocol-buffers/docs/overview
ProtoBuf.js
上面抄的内容不是本文重点,重点是 Google 没有推出官方的 JavaScript 库,在神奇的同性交友社区 Github 上,我找到了一个纯绿色无公害的 ProtoBuf.js 库。它是一个由纯JavaScript 实现构建在 ByteBuffer.js 之上的
.proto文件解析库,包含
Message 构建、数据序列化和反序列化等功能。
Google Protocol Buffers 传输的数据是二进制格式,JavaScript 天生不具备处理二进制数据的能力,所以要依赖 ByteBuffer.js ,ByteBuffer 和 ProtoBuf 都是由同一个团队 dcode.io 出品,ByteBuffer
可以单独使用,兼容 IE8+。
.proto
文件
.proto文件是 Protocol Buffers 的结构化数据定义,结构化数据被称为 Message,具体的就不解释了,可以看最末的两篇参考文章。
ProtoBuf.js 可以解析
.proto,构建 Message 对象,实现数据的序列化和反序列化,对于
.proto不了解可以看官方文档:https://developers.google.com/protocol-buffers/docs/proto3
下面举几个例子简单说明:
.proto文件初始化和构建 Message,例子参见:https://github.com/dcodeIO/ProtoBuf.js/blob/master/examples/websocket/www/index.html
1 2 | var builder = ProtoBuf.loadProtoFile("./example.proto"); var Message = builder.build("Message"); |
.proto,只需在构建时把包名带上就行。
1 2 | var builder = ProtoBuf.loadProtoFile("./example.proto"); var Message = builder.build("com.xxx.Message"); |
loadProtoFile()会让
.proto文件明文暴露,所以可以使用
ProtoBuf.js 提供的工具将
.proto转义成
json或
js,参见:https://github.com/dcodeIO/ProtoBuf.js/wiki/pbjs
安装 node 模块:
1 | npm install -g protobufjs |
1 | pbjs src/address_book.proto -t js |
1 23 | var _root = dcodeIO.ProtoBuf.newBuilder({})['import']({ |
.proto文件里面会有很多个 Message 类型,所以会将输出结果保存为一个 builder,
1 23 | var builder = dcodeIO.ProtoBuf.newBuilder({})['import']({ |
1 23 | var Message = builder.build("Message"); var msg = new Message({ text: 'message from maxzhang.' }); |
序列化和反序列化
在 Web 端使用 Protocol Buffers 时,无论发送还是接收的数据都应当是二进制格式,二进制数据可以直接使用 Message 类型对象解析,1 23 | // 序列化 function encode(jsonData) { var Message = builder.build("Message"); var msg = new Message(jsonData); return msg.toArrayBuffer(); } // 反序列化 function decodeMessage(data) { var msg = builder.build("Message").decode(data); return msg; } |
decode()返回一个 Message 实例对象(可以等同于 JSON Object),实例中的属性便是
.proto文件中声明的变量与类型,
在
.proto文件中声明数据类型需要遵循 Protocol
Buffers 数据类型 规则,如下表:
由于上图不包括 JavaScript 对应的数据类型,所以我自己补充了一个数据类型对应关系(每种数据类型我并没有一一验证使用过,可能有误,欢迎指正):
.proto Type | JavaScript Type |
---|---|
double | Long |
float | float |
int32 | int |
int64 | Long |
uint32 | int |
uint64 | Long |
sint32 | int |
sint64 | Long |
fixed32 | int |
fixed64 | Long |
sfixed32 | int |
sfixed64 | Long |
bool | boolean |
string | string |
bytes | ByteBuffer |
ByteBuffer.js
bytes 类型是二进制格式数据,需要使用 ByteBuffer.js 处理,ByteBuffer 可以直接操作二进制数据,例子:1 23 | var ByteBuffer = require("bytebuffer"); var bb = new ByteBuffer() .writeIString("Hello world!") .flip(); console.log(bb.readIString() + " from ByteBuffer.js"); |
1 23 | // 写入数据格式 len of id(4bits) + id(12bits) var bb = new ByteBuffer(16); var id = 1; bb.writeInt8(String(id).length << 4); bb.writeInt8(id); bb.flip(); |
在 Message API 中的
toArrayBuffer()
toBuffer()等方法底层实际调用的是
ByteBuffer 的接口,与 ByteBuffer 不同的是“Message 对象是按照 JSON 的方式修改值,调用
toArrayBuffer()接口序列化数据,调用
decode()接口反序列数据”。
Long.js
由于 JavaScript 精度问题,所以 int64和
uint64等类型数据会被转换成 Long.js 对象实例,Long
并不太复杂,与 bignumber.js 类似,具体参考 Long.js
API.
WebSocket
关于 WebSocket 提供一个简单的例子,实际应用与例子差不多,就是做两件基础的事:
连接 WebSocket,从 socket 通道拿到二进制数据,反序列化解析成 Message 对象。
实例化 Message 对象,然后序列化成二进制数据,发送给服务端。
参考文章
http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/http://www.cnblogs.com/royenhome/archive/2010/10/29/1864860.html
相关文章推荐
- ProtoBuf.js 使用技巧
- WebSocket中关于使用ProtoBuf传输数据介绍js部分
- 在cocos creator中使用protobufjs(一)
- 在cocos creator中使用protobufjs(四)
- 在TS语言H5项目中使用Protobufjs(二) - Layaair腊鸭引擎篇
- 在node中使用protobuf.js
- 在TS语言H5项目中使用Protobufjs(一) - Egret白鹭引擎篇
- 白鹭egret配合protobufjs的使用
- 基于Netty5.0高级案例二之WebSocket中关于使用ProtoBuf传输数据介绍js部分
- cocos creator中使用protobuf(dcodeIO/protobuf.js 5.0)
- 在cocos creator中使用protobufjs(二)
- 在cocos creator中使用protobufjs(三)
- WebSocket中关于使用ProtoBuf传输数据介绍js部分
- Protobuf在微信小游戏开发中的使用技巧
- js使用107个技巧
- JS中的使用技巧
- google protobuf java 简单使用
- Android上GTalk以及Push机制的XMPP数据选择使用protobuf格式而非XML格式
- [JS]JavaScript使用技巧精萃
- VS2010技巧:如何在js文件中使用jQuery智能感知