java 游戏 protobuf,Unity 3D Protobuf的使用 信息的简单发送 并在Java服务器上接受显示...

做过有网络相关游戏的人都知道protobuf,google的一套开源工具,用于发送信息的序列化和反序列化,是一个非常重要的网络工具。下面给大家介绍的是使用Protobuf用来实现信息的发送,并让信息在Java服务器上接受显示,想了解的同学可以看看。

这边提供我工程中使用的protobuf和其转换器:

http://download.csdn.net/detail/u012632851/9760880

我们做的是客户端,首先说Unity方面的导入吧。

Unity直接导入cs的源代码,而不是dll文件,其实差不多。我的资源的话直接把根目录下的protobuf-net拖入Unity工程就行了,不过网上自己去下载最新版本的同学可能会碰到两个问题:

34ae0b4d6bbb1c9b7c90e2ef8ef6a524.png

1.如上图,说使用了不安全的代码,这个时候只要在Assets目录下新建一个smcs.rsp的文件,内容是-unsafe,保存后重启Unity就能通过运行了;

d96963b7eafae4fb3f3d4079512b177f.png

2.MetaType中有无法解析的符号,这个去vs中看的话,它会提示你我们用的C#版本是4,而语法的版本是6,这个无法解决。我最后是直接替换老版本的MetaType脚本进去,其他的还是新的,然后就没有任何错误了。

环境搭建完成之后接下来就是制作与服务器通信的类了,直接看例子,以下是通信协议:

5257b79f0b26175a59c071af417f2c23.png

文件名称并非是无关紧要的,common会转换成C#中的namespace,而message后面的mymessage会转换成具体的类。

使用的时候就应该这样使用:

using common;

mymessage myMsg = new mymessage();

这里有个坑,大家也看到了java_package的一行,没错,在java的转换中文件名就是个类,而mymessage是个内部类,所以使用java_package指定包名,大家可以试试不写的结果,我查了一下,没找到导入默认包的方法。

使用的时候如此使用:

import protobuf.Common;

Common.mymessage.Builder msg2b = Common.mymessage.newBuilder();

Common.mymessage msg2 = msg2b.build();

byte[] b = msg2.toByteArray();

现在这些代码是无法使用的,接下来就是转换器,把上面协议的内容转换成C#、Java代码,可以参考我资源中message文件夹下的makeProtobuf.bat文件。

贴出来给大家看看吧,没什么好说的,就是使用相应的exe应用程序进行转换:

@echo off

set tool=..\protobuf-net\net

rem ============================================

rem Support

set proto=common.proto

%tool%\protogen.exe -i:%proto% -o:%proto%.cs -q

set proto=message.proto

%tool%\protogen.exe -i:%proto% -o:%proto%.cs -q

..\protobuf-java\protoc.exe -I=. --java_out=. common.proto

..\protobuf-java\protoc.exe -I=. --java_out=. message.proto

pause

没有问题的话就直接输出请继续字样的提示。

运行之后会出现如下的文件:

704c4ca707001bf69142ae26c5b90aed.png

protobuf中的是java的,而两个cs文件是Unity的。

Unity是最方便的,这两个文件你随便放哪都行,当然工程中要导入protobuf的前期下哈。

接下来是发送协议数据的代码:

using UnityEngine;

using System.IO;

using ProtoBuf;

using common;

public class ProtobufTest : MonoBehaviour {

SocketSink socketSink;

// Use this for initialization

void Start () {

socketSink = SocketSink.getInstance();

}

float dTime = 0f;

float maxDTime = 1f;

// Update is called once per frame

void Update () {

// 如果服务器没有连接

if(!socketSink.isConnected)

{

dTime = Time.deltaTime;

if(dTime > maxDTime)

{

dTime = 0f;

socketSink.init(); //每隔一秒重连一次服务器

}

}

}

private void OnGUI()

{

// 连上服务器之后,可以发送消息

if(socketSink.isConnected)

{

if(GUILayout.Button("发送"))

{

//socketSink.sendDataToServer("hello#");

// 建立一个消息

mymessage myMsg = new mymessage();

myMsg.myid = 1;

myMsg.message = "haha";

using (MemoryStream ms = new MemoryStream())

{

// 进行序列化

Serializer.Serialize(ms, myMsg);

byte[] data = new byte[ms.Length];

ms.Position = 0;

ms.Read(data, 0, data.Length); //将序列化完成的数据方法byte数组中

// 向服务器发送

socketSink.sendProtobufDataToServer(data);

}

}

}

}

}

一个简单的事例,就是按下屏幕的按钮就会发送数据。额,SocketSink是客户端建Socket底层的代码,在这就不提供给大家了,如果有问题可以评论区里提问,实在有需要的话,我可以考虑提供一下(不过估计没什么人看,哈哈)。

这样Unity上的开发就搞定了。

接下来是服务器,Eclipse上的开发是蛋疼的,感觉大学里学的java都白学了。。。

安装完成后,新建个java项目输出Helloworld看看有没有问题,嗯对,普通项目就可以了。

首先将资源中的protobuf-java-2.5.0.jar导入工程,再将之前协议转换出来的Java代码导入,最后的目录结构是这样:

46fc9e3f9e966c0c507561a9fee8808d.png

这个完成之后,只要开一下Socket服务器监听,然后接受Unity发送来的数据就可以了。

下面是Java代码:

public class SimpleServer {

public static void main(String[] args)

{

try{

// 服务器监听的总类,只存在一个,端口是5200

ServerSocket serverSocket=new ServerSocket(5200);

Socket socket=null;

while(true){

// 获取Unity客户端的连接,每有一个客户端,对应一个Socket

socket=serverSocket.accept();

// 开启监听线程

SimpleServerThread serverThread=new SimpleServerThread(socket);

serverThread.start();

InetAddress address=socket.getInetAddress();

System.out.println("来了一个客户端:" address.getHostAddress());

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

上面开启了一个监听,具体处理交给了SimpleServerThread,下面是具体脚本:

public class SimpleServerThread extends Thread {

Socket socket = null; // 记录客户端对应的Socket

SimpleServerThread(Socket socket)

{

this.socket = socket;

}

public void run()

{

System.out.println("读取线程启动");

//循环读取数据

while(true)

{

try{

System.out.println("读取中。。。");

// StringBuilder sb = new StringBuilder();

byte[] bs = new byte[1024]; //存放消息的byte数组

InputStream is = socket.getInputStream(); //socket产生的一个读入流

int len = -1;

// 读入

len = is.read(bs);

// 转换成对应长度的数组,这里绝对是不能这么写的,不过具体处理方法暂时没想到,以后看看会不会完善一下,嘛,毕竟这是服务端的事情

byte[] mybs = new byte[len];

for(int i=0 ; i < mybs.length ; i)

{

mybs[i] = bs[i];

}

// 将获取到的数据转换成相应的类

Common.mymessage msg = Common.mymessage.parseFrom(mybs);

int id = msg.getMyid();

String m = msg.getMessage();

// 打印

System.out.println(id ":" m);

}

catch(IOException e)

{

e.printStackTrace();

}

}

}

}

这样Unity中点击发送,Eclipse里应该能接受到信息了。最终效果再来个图:

b51c66ee4c07a7512d6791459428b952.png

这篇博文我弄了我两天,主要找资源、搞Java的时候费了很长时间,最后总结一句话Java真NM蛋疼,哈哈。

国内的文章就是实用性高,高手看了嗤之以鼻,新手看了如获至宝,讲真的我觉得我还挺适合这样的实战学习的,不喜欢光搞理论。

希望能快点成长到嗤之以鼻的阶段。

来自:http://blog.csdn.net/u012632851/article/details/56489777

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值