1.关于protocol buffer的使用和简介可以参考以下3篇博客
(1)语言规范 http://www.cnblogs.com/stephen-liu74/archive/2013/01/02/2841485.html
(2)c++实例 http://www.cnblogs.com/stephen-liu74/archive/2013/01/04/2842533.html
(2)java实例 http://www.cnblogs.com/stephen-liu74/archive/2013/01/06/2842972.html
2.protocol buffer的下载以及安装
(1)在VS环境中(C++)
一、把protocol-2.4.1.zip下载下来,解压后进入vsprojects目录,运行libprotobuf.vcproj,生成其中的四个项目
二、生成完之后,把protocol目录下的Debug/release目录添加到环境变量里面。
三、利用protoc.exe 将一个proto文件转换成cpp文件代码(详情见1.的博客介绍)
四、把生成的代码导入项目,并且配置项目的属性,
1)右键项目-》属性-》C/C++ -》常规,设置附加包含目录,改成所下数据包的src目录。
2)属性-》链接器-》常规,设置附加包含目录,改成vsprojects目录下编译后的release目录。
3)定位到属性-》输入-》附加依赖项,添加libprotobuf.lib libprotoc.lib
(2)在eclipse环境中(Java)
一、利用protoc.exe 将一个proto文件转换成java文件代码(详情见1.的博客介绍)
二、在项目中导入生成的文件
三、下载protocol-2.4.1.jar,导入项目
3.对cocos2dx客户端和mina服务器的修改
1)cocos2dx发送:由于protocol提供将message的语言对象(貌似很难理解,请看完上面3篇博客)转换成字符数组,所以发送不需要改动。
LoginReqMessage loginMsg; loginMsg.set_acctid(20); loginMsg.set_passwd("Hello World"); int length = loginMsg.ByteSize(); char* buf = new char[length]; loginMsg.SerializePartialToArray(buf,length); CCLog("length = %d",length); ::send(HSocket::socketHandle,buf,length,0);
2)mina的接受:
这里我发现了一篇很好的博客,是有关于mina结合protocol buf 的:http://blog.csdn.net/mrliu20082009/article/details/6977746
a.主要的修改是mina的过滤器改成StreamWriteFilter。这是因为protocol buf良好的支持字节流,所有要使用此过滤器
b.mina的handler改成用IoBuffer来缓冲
IoBuffer buffer = (IoBuffer)message; ByteBuffer bf = buffer.buf(); byte[] buf = new byte[bf.limit()]; bf.get(buf); LoginReqMessage loginReq = LoginReqMessage.parseFrom(buf); System.out.println(loginReq.getAcctID());
3)mina的返回
不能直接write字节数组,必须使用IoBuffer对象(因为是字节流),flip方式是必须调用的,否则客户端无法获得数据。
LoginReqMessage.Builder loginReqBuilder = LoginReqMessage.newBuilder(); loginReqBuilder.setAcctID(20); loginReqBuilder.setPasswd("hello fuck world"); LoginReqMessage backMessage = loginReqBuilder.build(); int length = loginReq.getSerializedSize(); System.out.println("Size=" + length); System.out.println(loginReq.toString()); byte[] bb = backMessage.toByteArray(); IoBuffer resp = IoBuffer.allocate(bb.length); resp.put(bb,0,bb.length); resp.flip(); session.write(resp); System.out.println("已经返回信息了");
4)cocos2dx的接受
因为BSD socket中的recv必须知道返回的字符数组的长度,所以我先定义了一个很大的数组,并且全用' '初始化。
之后在转换成message对象的时候,直接用strlen函数就可以准确的获取长度了。
char back[100]; memset(back,100,' '); ::recv(HSocket::socketHandle,back,100,0); LoginReqMessage loginMsg2; loginMsg2.ParseFromArray(back,strlen(back)); CCLOG("id=%I64d",loginMsg2.acctid()); CCLOG("backMsg=%s",back);