打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Unity3D & Java 基于 Protobuf 通信实现

Unity3D & Java 基于 Protobuf 通信实现

最近研究Unity3D,同时需要给游戏制定一套通信协议。因为本人是后端出生,对C#的 Socket相关通信框架不太熟悉,经过几天的学习,终于搞定了。在这里公布出来,大家可以共同学习,少走弯路。
本文重点:演示怎么解析和发送协议。

技术选型


服务端1
Java7
netty 4
客户端2
C#
SuperSocket.ClientEngine https://clientengine.codeplex.com/
它是从SuperSocket中分离出来的,不人性的是竟然没使用教程
通信协议3
Protobuf https://github.com/google/protobuf/
因为Protobuf 官方只支持 Java,C++,Pythone语言,C#需要第三方支持
protobuf-csharp https://code.google.com/p/protobuf-csharp-port/

Protobuf 相关的使用,请自行Gooogle,后面的代码会展示相关API, Goole打不开买一个代理一个月20RMB

开发前准备


协议解析,无论任何语言协议解析在通信中使用中都是必须的。要成功的解析协议,必须先搞清楚协议是如何制定的。
Protobuf 是基于 变长消息头(length) + 消息体(body)

Proto生成

message Request {    required string command = 1;    required string data = 2;}message Response {    required string command = 1;    required string data = 2;}

至于怎么生成,我这里就不给出详细方式了,通过Protobuf资料,有详细说明。

客户端代码


        public static DataEventArgs buffer = new DataEventArgs();         public static int count = 0;        public static void Main (string[] args)        {            buffer.Data = new byte[8192]; //8 KB            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001);            //supersocket clientengine             AsyncTcpSession client = new AsyncTcpSession (endPoint);            client.Connected += OnConnected;            client.DataReceived += OnDataReceive; //重点解析在这里            //连接服务器            client.Connect ();            //构造Message,属性Protobuf的人应该都能看懂            Request.Builder builder = Request.CreateBuilder ();            builder.SetCommand ("110");            builder.SetData ("1231231232131");            Request request = builder.BuildPartial ();              sendMessage (client, request);            Thread.Sleep (30000);        }        public static void OnConnected(Object sender, EventArgs e)        {            Console.WriteLine ("connect to server finish.");        }        /**        * 这里 C# 的实现和Protobuf 官方给的Java实现是一样的        */        public static void sendMessage(AsyncTcpSession client, Request request)        {            using(MemoryStream stream = new MemoryStream())            {                CodedOutputStream os = CodedOutputStream.CreateInstance(stream);                //一定要去看它的代码实现,                os.WriteMessageNoTag(request);                 /**                * WriteMessageNoTag 等价于 WriteVarint32, WriteByte(byte[])                * 也就是:变长消息头 + 消息体                */                os.Flush();                byte[] data = stream.ToArray();                client.Send ( new ArraySegment<byte>(data) );            }        }        /**        * 协议解析,把这里搞明白了,就没白看        */        public static void OnDataReceive(Object sender, DataEventArgs e)         {            //DataEventArgs 里面有 byte[] Data是从协议层接收上来的字节数组,需要程序端进行缓存            Console.WriteLine ("buff length: {0}, offset: {1}", e.Length, e.Offset);            if( e.Length <= 0 )            {                return;            }            //把收取上来的自己全部缓存到本地 buffer 中            Array.Copy (e.Data, 0, buffer.Data, buffer.Length, e.Length);            buffer.Length += e.Length;            CodedInputStream stream = CodedInputStream.CreateInstance (buffer.Data);            while ( !stream.IsAtEnd )             {                //标记读取的Position, 在长度不够时进行数组拷贝,到下一次在进行解析                int markReadIndex = (int)stream.Position;                //Protobuf 变长头, 也就是消息长度                int varint32 = (int)stream.ReadRawVarint32();                if( varint32 <= (buffer.Length - (int)stream.Position) )                {                    try                    {                        byte[] body = stream.ReadRawBytes (varint32);                        Response response = Response.ParseFrom (body);                                              Console.WriteLine("Response: " + response.ToString() + ", count: " + (++count));                        //dispatcher message, 这里就可以用多线程进行协议分发                    }catch(Exception exception)                    {                        Console.WriteLine(exception.Message);                    }                }                 else                 {                    /**                    * 本次数据不够长度,缓存进行下一次解析                    */                    byte[] dest = new byte[8192];                    int remainSize = buffer.Length - markReadIndex;                    Array.Copy(buffer.Data, markReadIndex, dest, 0, remainSize);                    /**                     * 缓存未处理完的字节                      */                    buffer.Data = dest;                    buffer.Offset = 0;                    buffer.Length = remainSize;                    break;                }            }        }

后记


客户端完整代码打包:http://download.csdn.net/detail/zeus_9i/8748899

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Java数据通讯中使用Google Protobuf 序列化与反序列化
Protocol Buffer技术详解(Java实例)
android 中okhttp post请求传递json数据
译文
Unity手游之路<三> 基于Unity+Java的聊天室源码
深入了解 gRPC:协议
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服