Archive for the ‘Protobuf’ Category

Protobuf-net在Unity中的序列化与反序列化

星期日, 五月 18th, 2014 18 views

本篇中我们只讲解如何在Unity中对Protobuf-net进行序列化(Serialize)与反序列化(Deserialize),关于Unity的socket网络通信部分我们后续开篇。

首先去Protobuf-net的Google下载点下载protobuf-net类库:https://code.google.com/p/protobuf-net/downloads/list
这里用的是目前最新的protobuf-net r668
下载完毕后打开压缩包,在Full\unity中找到protobuf-net.dll将其添加到项目中。
接下来过程其实类似于我之前的一文章《Protobuf在Java中的简单实例》

①创建proto文件,定义协议格式
首先我们需要创建一个.proto文件来进行测试:

1
2
3
4
5
package com.beitown.net.msg;//包名
message TestMsg {
    required int64 Id=1;
    required string Name=2;
}

每个字段后标记的“=1”、“=2”这里就不解释了,之前的一篇Protobuf文章中已经做过概述。

②编译Proto文件生成.cs文件
这里我们需要用到一个编译工具ProtoGen,在之前下载的protobuf-net r668.zip中就有。
为了方便管理.proto和.cs文件以及编译快捷,我们可以写一个bat脚本来实现自动编译.proto文件,脚本如下:

1
2
3
@echo off
for /f "delims=" %%i in ('dir /b proto "proto/*.proto"') do protogen -i:proto/%%i -o:cs/%%~ni.cs
pause

(更多…)

Protobuf-net在Unity WebPlayer中的兼容解决方案

星期四, 五月 15th, 2014 12 views

由于项目需要所以使用了Unity + Protobuf。
但是问题随之而来,因为Protobuf是JIT运行时动态编译的,而Unity不支持这种运行时动态编译,同时Protobuf是基于.net2.0框架的,因此当项目发布在PC时,出现了异常:

1
2
3
4
5
6
7
8
9
10
ArgumentOutOfRangeException: Argument is out of range.

Parameter name: options
at System.Text.RegularExpressions.Regex.validate_options (RegexOptions options) [0x0003a] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/System/System.Text.RegularExpressions/Regex.cs:248

at System.Text.RegularExpressions.Regex..ctor (System.String pattern, RegexOptions options) [0x00017] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/System/System.Text.RegularExpressions/Regex.cs:214

at Google.ProtocolBuffers.Descriptors.DescriptorPool..cctor () [0x00000] in :0
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for Google.ProtocolBuffers.Descriptors.DescriptorPool
......

这里使用的是Protobuf-Csharp包,通过排查,在发布时将PlayerSetting中Api Compatibility Level 设置成.Net 2.0即可解决。

如图

但当需要发布到WebPlayer的时候,发现一个基本无解的问题——WebPlayer PlayerSetting中的Api Compatibility Level按钮是灰色的!只支持.Net 2.0 subset模式,因此发布后依然无法解决protobuf异常问题。
(更多…)

Protobuf在Java中的简单实例

星期日, 五月 11th, 2014 16 views

关于protobuf的介绍请大家自行查看https://code.google.com/p/protobuf/,本篇直奔主题——如何实现一个最简protobuf的Demo

①定义协议格式
首先定义.proto文件,可参考https://developers.google.com/protocol-buffers/docs/proto

大体格式如下:

1
2
3
4
5
package com.beitown.net.msg;//包名
message TestMsg {
    required int64 Id=1;
    required string Name=2;
}

每个字段后标记的“=1”、“=2”,是在二进制编码时使用的每个字段的唯一标识。在编码时,数字1~15要比大于它们的数字少一个字节,因此,作为一个优化选项,可以把1~15的数字用于常用的或重复性的元素。
将其保存为test.proto文件

②编译ProtocolBuffer
运行ProtocolBuffer编译器protoc来生成与.proto文件相关的类
首先我们已经有了一个protoc.exe文件(生成方式不再赘述,需要的可自行查找)
官方给出的编译语句为 protoc -I=$SRC_DIR –java_out=$DST_DIR $SRC_DIR/test.proto
打开cmd命令行窗口,先cd到protoc.exe所在文件夹为根文件夹,此时输出的java源码在根文件夹下的src子文件夹中,test.proto文件在proto子文件夹中,因此命令如下

1
protoc --java_out=src proto/test.proto

若出现提示 Expected top-level statement (e.g. “message”) 为编码格式问题,(win7下)解决方法是使用记事本打开后另存为ANSI格式。
编译通过后会在目标文件夹即可 src/com/beitown/net/msg 下生成一个Test.java文件,我们可以对这个类的操作来实现protobuf内容的读取和写入。

③创建Message实例-序列化
接下来将说明如何对上文中的Test类进行操作,上文中定义了TestMsg这个结构体,因此创建代码如下

1
2
3
TestMsg msg = TestMsg.newBuilder().setId(001).setName("beitown").build();
msg.toByteArray();
//发送msg.toByteArray()字节流

这里的setID,setName即为protoc自动生成Test.java中自带的方法。以上即可看出对于自定数据结构我们已经无需再去关心其从二进制转为消息类的过程,即将开发从通信层剥离出来,程序只需要关心消息类的处理逻辑。

③读取Message实例-反序列化

1
2
3
4
5
//接收到字节流
byte[] data = 二进制流对象转换的字节数组;
TestMsg msg = TestMsg.parseFrom(data);
int id = msg.getId();
String name =  msg.getName();

以上即为一个protobuf在java中的简单运用实例,通过对字节数组的发送和接收来实现protobuf消息的通信。
本篇针对初次接触protobuf的朋友做为学习参考之用,更多高级应用请自行举一反三。
本篇到此,谢谢关注。

BeiTown
2014-05-11