Cocos2d-x游戏开发_客户端与服务器的交互(2)使用protocol buffer

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);

  

原文地址:https://www.cnblogs.com/hezijian/p/3758091.html