protoBuf是一種靈活高效的獨立於語言平臺的結構化數據表示方法,與XML相比,protoBuf更小更快更簡單。你能夠用定義本身protoBuf的數據結構,用ProtoBuf編譯器生成特定語言的源代碼,如C++,Java,Python等,目前protoBuf對主流的編程語言都提供了支持,很是方便的進行序列化和反序列化。javascript
特色:html
目前最新版本爲Protocol Buffers v3.5.1前端
解壓 protoc-3.5.1-osx-x86_64.zip
java
Mac 配置環境變量 vi ~/.bash_profile
使其配置生效source ~/.bash_profile
git
#protobuf export PROTOBUF_HOME=/Users/Javen/Documents/dev/java/protobuf/protoc-3.5.1-osx-x86_64 export PATH=$PATH:$PROTOBUF_HOME/bin
Window 將bin添加到path 便可 例如:D:\protobuf\protoc-3.5.1-win32\bin
github
本文在Mac環境下編寫
Mac與window命令惟一的區別就是須要將protoc
改爲protoc.exe
前提是須要添加環境變量。typescript
文件保存爲chat.proto
此proto
文件摘自t-io 讓天下沒有難開發的網絡編程npm
syntax = "proto3"; package com.im.common.packets; option java_package = "com.im.common.packets"; //設置java對應的package option java_multiple_files = true; //建議設置爲true,這樣會每一個對象放在一個文件中,不然全部對象都在一個java文件中 /** * 聊天類型 */ enum ChatType { CHAT_TYPE_UNKNOW = 0;//未知 CHAT_TYPE_PUBLIC = 1;//公聊 CHAT_TYPE_PRIVATE = 2;//私聊 } /** * 聊天請求 */ message ChatReqBody { int64 time = 1;//消息發送時間 ChatType type = 2; //聊天類型 string text = 3; //聊天內容 string group = 4; //目標組id int32 toId = 5; //目標用戶id, string toNick = 6; //目標用戶nick } /** * 聊天響應 */ message ChatRespBody { int64 time = 1;//消息發送時間 ChatType type = 2; //聊天類型 string text = 3; //聊天內容 int32 fromId = 4; //發送聊天消息的用戶id string fromNick = 5; //發送聊天消息的用戶nick int32 toId = 6; //目標用戶id string toNick = 7; //目標用戶nick string group = 8; //目標組id }
進入到項目的跟目錄執行如下編譯命名,com/im/common/packets
爲chat.proto
中的包名,chat.proto
文件放在com/im/common/packets
下。編程
protoc --java_out=./ com/im/common/packets/chat.proto
protoc --js_out=import_style=commonjs,binary:. chat.proto
執行後會在當前文件夾中生成chat_pb.js
文件,這裏面就是protobuf
的API和一些函數。若是是Node.js
就能夠直接使用了,若是想在瀏覽器(前端)中使用protobuf
還須要作一些處理。json
在chat_pb.js
文件的同級目錄下安裝引用庫
npm install -g require npm install google-protobuf npm install -g browserify
編寫腳本保存爲exports.js
var chatProto = require('./chat_pb'); module.exports = { DataProto: chatProto }
執行命令 browserify exports.js > chat.js
對chat_pb.js
文件進行編譯打包生成chat.js
後就能夠愉快的使用了。
<script src="./chat.js"></script> <script type="text/javascript"> var chatReqBody = new proto.com.im.common.packets.ChatReqBody(); chatReqBody.setTime(new Date().getTime()); chatReqBody.setText("測試"); chatReqBody.setType(1); chatReqBody.setGroup("Javen"); chatReqBody.setToid(666); chatReqBody.setTonick("Javen205"); var bytes = chatReqBody.serializeBinary(); console.log("序列化爲字節:"+bytes); var data = proto.com.im.common.packets.ChatReqBody.deserializeBinary(bytes); console.log("反序列化爲對象:"+data); console.log("從對象中獲取指定屬性:"+data.getTonick()); console.log("對象轉化爲JSON:"+JSON.stringify(data)); </script>
java中要用protobuf,protobuf與json相互轉換,首先須要引入相關的jar,maven的pom座標以下
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>com.googlecode.protobuf-java-format</groupId> <artifactId>protobuf-java-format</artifactId> <version>1.4</version> </dependency>
public static void test() { try { JsonFormat jsonFormat = new JsonFormat(); ChatRespBody.Builder builder = ChatRespBody.newBuilder(); builder.setType(ChatType.CHAT_TYPE_PUBLIC); builder.setText("Javen 測試"); builder.setFromId(1); builder.setFromNick("Javen"); builder.setToId(110); builder.setToNick("Javen.zhou"); builder.setGroup("Javen"); builder.setTime(SystemTimer.currentTimeMillis()); ChatRespBody chatRespBody = builder.build(); //從protobuf轉json String asJson = jsonFormat.printToString(chatRespBody); System.out.println("Object to json "+asJson); byte[] bodybyte = chatRespBody.toByteArray(); //解碼是從byte[]轉換爲java對象 ChatRespBody parseChatRespBody = ChatRespBody.parseFrom(bodybyte); asJson = jsonFormat.printToString(parseChatRespBody); System.out.println("bodybyte to json "+asJson); //從json轉protobuf ChatRespBody.Builder _builder = ChatRespBody.newBuilder(); jsonFormat.merge(new ByteArrayInputStream(asJson.getBytes()), _builder); ChatRespBody _chatRespBody = _builder.build(); asJson = jsonFormat.printToString(_chatRespBody); System.out.println("json to protobuf "+asJson); } catch (Exception e) { e.printStackTrace(); } }
將chat.js
中的var global = Function('return this')();
修改成
// var global = Function('return this')(); var global = (function(){ return this; })()
BK.Script.loadlib('GameRes://qqPlayCore.js'); BK.Script.loadlib('GameRes://tio/chat.js'); function test() { var ws = new BK.WebSocket("ws://127.0.0.1:9326?group=test&name=Javen"); ws.onOpen = function(ws) { BK.Script.log(1, 0, "onOpen.js"); BK.Script.log(1, 0, "1.readyState = " + ws.getReadyState()); var time = 0; BK.Director.ticker.add(function(ts, duration) { time = time + 1; if (time % 100 == 0) { // ws.send("phone test" + time); var chatReqBody = new proto.com.im.common.packets.ChatReqBody(); chatReqBody.setTime(new Date().getTime()); chatReqBody.setText("phone test" + time); chatReqBody.setType(1); chatReqBody.setGroup("test"); var bytes = chatReqBody.serializeBinary(); ws.send(bytes); } }); }; ws.onClose = function(ws) { BK.Script.log(1, 0, "onClose.js"); BK.Script.log(1, 0, "1.readyState = " + ws.getReadyState()); }; ws.onError = function(ws) { BK.Script.log(1, 0, "onError.js"); BK.Script.log(1, 0, "1.readyState = " + ws.getReadyState()); BK.Script.log("onError.js.js getErrorCode:" + ws.getErrorCode()); BK.Script.log("onError.js getErrorString:" + ws.getErrorString()); }; ws.onMessage = function(ws, event) { if (!event.isBinary) { var str = event.data.readAsString(); BK.Script.log(1, 0, "text = " + str); } else { var buf = event.data; //將遊標pointer重置爲0 buf.rewind(); var ab = new ArrayBuffer(buf.length); var dv = new DataView(ab); while (!buf.eof) { dv.setUint8(buf.pointer, buf.readUint8Buffer()); } var chatRespBody = proto.com.im.common.packets.ChatRespBody.deserializeBinary(ab); var msg = chatRespBody.getFromnick() + " 說: " + chatRespBody.getText(); BK.Script.log(1, 0, "text = " + msg); } }; ws.onSendComplete = function(ws) { BK.Script.log(1, 0, "onSendComplete.js"); }; ws.connect(); } test();
egret有提供將proto文件
生成JS以及TS的工具
npm install protobufjs -g npm install @egret/protobuf -g
一、在白鷺項目的根目錄中新建protobuf
文件夾,再在protobuf
文件夾中新建protofile
文件夾
二、將proto
文件放到protofile
文件夾中
三、依次執行pb-egret add
、pb-egret generate
將會自動完成如下操做:
一、在tsconfig.json
中的include
節點中添加protobuf/**/*.d.ts
二、在egretProperties.json
中的modules
節點添加
{ "name": "protobuf-library", "path": "protobuf/library" }, { "name": "protobuf-bundles", "path": "protobuf/bundles" }
三、在protobuf
文件夾中自動生成bundles
以及library
文件夾裏面包含了咱們須要的js以及ts
處理髮送消息
private sendReq(text:string,group:string){ var chatReqBody = new com.im.common.packets.ChatReqBody(); chatReqBody.time = new Date().getTime(); chatReqBody.text = text; chatReqBody.type = com.im.common.packets.ChatType.CHAT_TYPE_PUBLIC; chatReqBody.group = group; let data = com.im.common.packets.ChatReqBody.encode(chatReqBody).finish(); this.sendBytesData(data); } private sendBytesData(data:Uint8Array){ this.socket.writeBytes(new egret.ByteArray(data)); }
處理接收消息
private onReceiveMessage(e:egret.Event):void { //建立 ByteArray 對象 var byte:egret.ByteArray = new egret.ByteArray(); //讀取數據 this.socket.readBytes(byte); let buffer = new Uint8Array(byte.buffer); let chatRespBody = com.im.common.packets.ChatRespBody.decode(buffer); // this.trace("收到數據:"+JSON.stringify(chatRespBody)); this.trace(chatRespBody.fromNick+" 說: "+chatRespBody.text); }
Cocos Creator中使用protobuf與前端中使用protobuf操做步驟基本同樣,只是在Cocos Creator中須要將JS導入爲插件
將5.2中編譯生成的JS導入到工程的腳本文件夾中,打開Cocos Creator就會提示您是否要將腳本設置爲插件。
與6.1前端中使用方式同樣。
start: function () { cc.log("start"); let chatReqBody = new proto.com.im.common.packets.ChatReqBody(); chatReqBody.setTime(new Date().getTime()); chatReqBody.setText("測試"); chatReqBody.setType(1); chatReqBody.setGroup("Javen"); chatReqBody.setToid(666); chatReqBody.setTonick("Javen205"); let bytes = chatReqBody.serializeBinary(); cc.log("序列化爲字節:" + bytes); let data = proto.com.im.common.packets.ChatReqBody.deserializeBinary(bytes); cc.log("反序列化爲對象:" + data); cc.log("從對象中獲取指定屬性:" + data.getTonick()); cc.log("對象轉化爲JSON:" + JSON.stringify(data)); },
到這裏如何使用protobuf就介紹完了,我的能力有限若有錯誤歡迎指正。你有更好的解決方案或者建議歡迎一塊兒交流討論,若有疑問歡迎留言。