Posts Tagged ‘JAVA’

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

HashMap中以动态对象作为Key值时的Remove陷阱

星期一, 十一月 5th, 2012 86 views

在游戏服务器上控制角色的坐标点可以通过Point这个类来实现,地图模块则以HashMap来承载。此问题从简单来说,既HashMap以Point作为Key值时,用户往往会忽略其中一个细节照成后期的非编译Bug。

以下是示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HashMap  <point ,String] hashMap = new HashMap<Point, String]();//把]换成>
Point A = new Point(2,2);
hashMap.put(A,"A");//将2,2点作为Key值存入HashMap
A.x = 1;//修改A点的x值
A.y = 1;//修改A点的y值
System.out.println(hashMap.get(A));//此时结果为Null 已经找不到了

//我们试着迭代一下
System.out.println(hashMap.size());//此处为1
for(Iterator<string ] iterator = hashMap.values().iterator();iterator.hasNext();)
{
    iterator.next();
    iterator.remove();
}
System.out.println(hashMap.size());//此处依旧为1 即无法销毁

(更多…)