久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Unity3D & Java 基于 Protobuf 通信實現(xiàn)

 阿修羅之獅猿授 2016-04-27

Unity3D & Java 基于 Protobuf 通信實現(xiàn)

最近研究Unity3D,,同時需要給游戲制定一套通信協(xié)議。因為本人是后端出生,,對C#的 Socket相關(guān)通信框架不太熟悉,,經(jīng)過幾天的學(xué)習(xí),終于搞定了,。在這里公布出來,,大家可以共同學(xué)習(xí),少走彎路,。
本文重點:演示怎么解析和發(fā)送協(xié)議,。

技術(shù)選型


服務(wù)端1
Java7
netty 4
客戶端2
C#
SuperSocket.ClientEngine https://clientengine./
它是從SuperSocket中分離出來的,不人性的是竟然沒使用教程
通信協(xié)議3
Protobuf https://github.com/google/protobuf/
因為Protobuf 官方只支持 Java,,C++,,Pythone語言,C#需要第三方支持
protobuf-csharp https://code.google.com/p/protobuf-csharp-port/

Protobuf 相關(guān)的使用,,請自行Gooogle,,后面的代碼會展示相關(guān)API, Goole打不開買一個代理一個月20RMB

開發(fā)前準備


協(xié)議解析,無論任何語言協(xié)議解析在通信中使用中都是必須的。要成功的解析協(xié)議,,必須先搞清楚協(xié)議是如何制定的,。
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; //重點解析在這里

            //連接服務(wù)器
            client.Connect ();

            //構(gòu)造Message,,屬性Protobuf的人應(yīng)該都能看懂
            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# 的實現(xiàn)和Protobuf 官方給的Java實現(xiàn)是一樣的
        */
        public static void sendMessage(AsyncTcpSession client, Request request)
        {
            using(MemoryStream stream = new MemoryStream())
            {
                CodedOutputStream os = CodedOutputStream.CreateInstance(stream);
                //一定要去看它的代碼實現(xiàn),,
                os.WriteMessageNoTag(request); 
                /**
                * WriteMessageNoTag 等價于 WriteVarint32, WriteByte(byte[])
                * 也就是:變長消息頭 + 消息體
                */

                os.Flush();

                byte[] data = stream.ToArray();
                client.Send ( new ArraySegment<byte>(data) );
            }
        }

        /**
        * 協(xié)議解析,把這里搞明白了,,就沒白看
        */
        public static void OnDataReceive(Object sender, DataEventArgs e) 
        {
            //DataEventArgs 里面有 byte[] Data是從協(xié)議層接收上來的字節(jié)數(shù)組,,需要程序端進行緩存
            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, 在長度不夠時進行數(shù)組拷貝,到下一次在進行解析
                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, 這里就可以用多線程進行協(xié)議分發(fā)

                    }catch(Exception exception)
                    {
                        Console.WriteLine(exception.Message);
                    }
                } 
                else 
                {
                    /**
                    * 本次數(shù)據(jù)不夠長度,緩存進行下一次解析
                    */
                    byte[] dest = new byte[8192];
                    int remainSize = buffer.Length - markReadIndex;
                    Array.Copy(buffer.Data, markReadIndex, dest, 0, remainSize);

                    /**
                     * 緩存未處理完的字節(jié) 
                     */
                    buffer.Data = dest;
                    buffer.Offset = 0;
                    buffer.Length = remainSize;

                    break;
                }
            }
        }

后記


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

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多