WeaveSocket框架-Unity太空大战游戏-客户端-3

WeaveSocket框架-Unity太空大战游戏-客户端-3




客户端代码结构




登陆界面




游戏场景




-------------------------------------

主要的逻辑流程

----------------------------------------------

启动程序

----------------------------------------------

玩家输入账号密码

----------------------------------------------

点击登陆按钮

----------------------------------------------

连接服务器(如果成功),继续发送账号密码到服务器的命令

----------------------------------------------

服务器接收账号密码,进行查找数据库操作

----------------------------------------------

发送查找结果给客户端......

----------------------------------------------

如果客户端接收到服务器发过来的登陆成功消息(跳转到游戏场景),

----------------------------------------------

如果返回失败,那么提示账号密码错误

----------------------------------------------

客户端再次发送查找当前用户的历史积分数据的命令

----------------------------------------------

(正在游戏场景运行中)

----------------------------------------------

客户端接受到历史积分数据,并更新显示到UnityUI界面上

----------------------------------------------

P0-玩家战机生命为0时,向服务器发送本次游戏积分数据

----------------------------------------------

服务器收到玩家本次游戏积分数据,进行数据库更新操作(根据用户名)

----------------------------------------------

客户端显示一个按钮,玩家可点击再玩一次,再次游戏(跳转P0,当玩家生命为0时)



客户端主要的代码类为WeaveSocketGameClient 



(WeaveSocket框架对应为P2PClient,这里是模仿改写的便于Unity游戏客户端使用,代码内部使用的LoomUnity多线程插件).................................................






using Frankfort.Threading;
using MyTcpCommandLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using UnityEngine;
using WeaveBase;

namespace MyTcpClient
{
    public class WeaveSocketGameClient
    {
        public Thread threadA;
        public Thread threadB;

        private ThreadPoolScheduler myThreadScheduler;


        WeaveBaseManager xmhelper = new WeaveBaseManager();

        /// <summary>
        /// 是否连接成功
        /// </summary>
        public bool isok = false;
        /// <summary>
        /// 在接收数据
        /// </summary>
        public bool isReceives = false;
        /// <summary>
        /// 是否在线了
        /// </summary>
        public bool IsOnline = false;
        
        DateTime timeout;
        /// <summary>
        /// 数据超时时间
        /// </summary>
        int mytimeout = 90;

        /// <summary>
        /// 队列中没有排队的方法需要执行
        /// </summary>
        List<TempPakeage> mytemppakeList = new List<TempPakeage>();

        public List<byte[]> ListData = new List<byte[]>();

        public string tokan;

        public String ip;
        public int port;

        public event ReceiveMessage ReceiveMessageEvent;
        public event ConnectOk ConnectOkEvent;

        public event ReceiveBit ReceiveBitEvent;
        public event TimeOut TimeOutEvent;
        public event ErrorMessage ErrorMessageEvent;

        public event JumpServer JumpServerEvent;

        public TcpClient tcpClient;

       // System.Threading.Thread receives_thread1;

       // System.Threading.Thread checkToken_UpdateList_thread2;


        SocketDataType s_datatype = SocketDataType.Json;
        public WeaveSocketGameClient(SocketDataType _type)
        {
            s_datatype = _type;
          
        }

        #region  客户端注册类,,服务端可以按方法名调用

        public void AddListenClass(object obj)
        {
            GetAttributeInfo(obj.GetType(), obj);
            //xmhelper.AddListen()

            //objlist.Add(obj);

        }
        public void DeleteListenClass(object obj)
        {
            deleteAttributeInfo(obj.GetType(), obj);
            //xmhelper.AddListen()

            //objlist.Add(obj);

        }
        public void deleteAttributeInfo(Type t, object obj)
        {
            foreach (MethodInfo mi in t.GetMethods())
            {
                InstallFunAttribute myattribute = (InstallFunAttribute)Attribute.GetCustomAttribute(mi, typeof(InstallFunAttribute));
                if (myattribute == null)
                {

                }
                else
                {
                    xmhelper.DeleteListen(mi.Name);
                }
            }
        }
        public void GetAttributeInfo(Type t, object obj)
        {
            foreach (MethodInfo mi in t.GetMethods())
            {
                InstallFunAttribute myattribute = (InstallFunAttribute)Attribute.GetCustomAttribute(mi, typeof(InstallFunAttribute));
                if (myattribute == null)
                { }
                else
                {
                    Delegate del = Delegate.CreateDelegate(typeof(WeaveRequestDataDelegate), obj, mi, true);
                    xmhelper.AddListen(mi.Name, del as WeaveRequestDataDelegate, myattribute.Type);
                }
            }
        }

        #endregion



        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="_ip">IP地址</param>
        /// <param name="_port">端口号</param>
        /// <param name="_timeout">过期时间</param>
        /// <param name="_takon">是否takon</param>
        /// <returns></returns>
        public bool StartConnect(string _ip, int _port, int _timeout, bool _takon)
        {
            mytimeout = _timeout;
            ip = _ip;
            port = _port;
            return StartConnectToServer(ip, port, _takon);
        }
        public bool RestartConnectToServer(bool takon)
        {
            return StartConnectToServer(ip, port, takon);
        }


        private bool StartConnectToServer(string _ip, int _port, bool _takon)
        {
            try
            {
                if (s_datatype == SocketDataType.Json && ReceiveMessageEvent == null)
                    Debug.Log("没有注册receiveServerEvent事件");

                if (s_datatype == SocketDataType.Json && ReceiveBitEvent == null)
                    Debug.Log("没有注册receiveServerEventbit事件");
                ip = _ip;
                port = _port;

                //tcpClient = new TcpClient(ip, port);
                tcpClient = new TcpClient();
                //  tcpc.ExclusiveAddressUse = false;

                try
                {
                    tcpClient.Connect(ip, port);
                }
                catch
                {
                    return false;
                }
                
                IsOnline = true;
                isok = true;

                timeout = DateTime.Now;
                if (!isReceives)
                {
                    isReceives = true;
                  

                    // ParameterThreadStart的定义为void ParameterizedThreadStart(object state),
                    // 使用这个这个委托定义的线程的启动函数可以接受一个输入参数,

                    //receives_thread1 = new System.Threading.Thread(new ParameterizedThreadStart(ReceivesThread));
                    //receives_thread1.IsBackground = true;
                   // receives_thread1.Start();
                    // ThreadStart这个委托定义为void ThreadStart(),也就是说,所执行的方法不能有参数
                  //  checkToken_UpdateList_thread2 = new System.Threading.Thread(new ThreadStart(CheckToken_UpdateListDataThread));
                    //checkToken_UpdateList_thread2.IsBackground = true;
                  //  checkToken_UpdateList_thread2.Start();

                    /*开始执行线程开始*/
                    myThreadScheduler = Loom.CreateThreadPoolScheduler();

                    //--------------- Ending Single threaded routine 单线程程序结束--------------------
                    threadA = Loom.StartSingleThread(ReceivesThread,null, System.Threading.ThreadPriority.Normal, true);
                    //--------------- Ending Single threaded routine 单线程程序结束--------------------

                    //--------------- Continues Single threaded routine 在单线程的程序--------------------
                    threadB = Loom.StartSingleThread(CheckToken_UpdateListDataThread, System.Threading.ThreadPriority.Normal, true);
                    //--------------- Continues Single threaded routine  在单线程的程序--------------------
                    /*开始执行线程结束*/

                }
                int ss = 0;

                if (!_takon)
                    return true;

                while (tokan == null)
                {
                    // System.Threading.Thread.Sleep(1000);
                    // Loom.WaitForNextFrame(10);
                    Loom.WaitForSeconds(1);
                    ss++;
                    if (ss > 10)
                        return false;
                }

                if(ConnectOkEvent != null)
                   ConnectOkEvent();

                return true;
            }
            catch (Exception e)
            {
                IsOnline = false;
                if (ErrorMessageEvent != null)
                    ErrorMessageEvent( 1 , e.Message);
                return false;
            }
        }


        #region  几个方法的方法

        public bool SendParameter<T>(byte command, String Request, T Parameter, int Querycount)
        {
            WeaveBase.WeaveSession b = new WeaveBase.WeaveSession();
            b.Request = Request;
            b.Token = this.tokan;
            b.SetParameter<T>(Parameter);
            b.Querycount = Querycount;
            return SendStringCheck(command, b.Getjson());
        }
        public bool SendRoot<T>(byte command, String Request, T Root, int Querycount)
        {
            WeaveBase.WeaveSession b = new WeaveBase.WeaveSession();
            b.Request = Request;
            b.Token = this.tokan;
            b.SetRoot<T>(Root);
            b.Querycount = Querycount;
            return SendStringCheck(command, b.Getjson());
        }
        public void Send(byte[] b)
        {
            tcpClient.Client.Send(b);
        }
        public bool SendStringCheck(byte command, string text)
        {
            try
            {
                //byte[] sendb = System.Text.Encoding.UTF8.GetBytes(text);
                //byte[] part3_length = System.Text.Encoding.UTF8.GetBytes(sendb.Length.ToString());
                //byte[] b = new byte[2 + part3_length.Length + sendb.Length];
                //b[0] = command;
                //b[1] = (byte)part3_length.Length;
                //part3_length.CopyTo(b, 2);
                //扩充 第四部分数据(待发送的数据)的长度,扩充到b数组第三位开始的后面
                //sendb.CopyTo(b, 2 + part3_length.Length);
                //扩充 第四部分数据实际的数据,扩充到b数组第三部分结尾后面...

                byte[] b = MyGameClientHelper.CodingProtocol( command,  text);

                int count = (b.Length <= 40960 ? b.Length / 40960 : (b.Length / 40960) + 1);
                if (count == 0)
                {
                    //判定数据长度,,实际指的是大小是不是小于40kb,,,
                    tcpClient.Client.Send(b);
                  
                }
                else
                {
                    for (int i = 0; i < count; i++)
                    {
                        int zz = b.Length - (i * 40960) > 40960 ? 40960 : b.Length - (i * 40960);
                        byte[] temp = new byte[zz];
                        Array.Copy(b, i * 40960, temp, 0, zz);
                        tcpClient.Client.Send(temp);
                        //分割发送......
                       // System.Threading.Thread.Sleep(1);
                        // Loom.WaitForNextFrame(10);
                        Loom.WaitForSeconds(0.001f);
                    }
                }
            }
            catch (Exception ee)
            {
                IsOnline = false;
                CloseConnect();
                if (TimeOutEvent != null)
                    TimeOutEvent();
              
                SendStringCheck(command, text);
                if (ErrorMessageEvent != null)
                    ErrorMessageEvent(9, "send:" + ee.Message);
                return false;
            }
            // tcpc.Close();

            return true;
        }
        public bool SendByteCheck(byte command, byte[] text)
        {
            try
            {
                //byte[] sendb = text;
                //byte[] lens = MyGameClientHelper.ConvertToByteList(sendb.Length);
                //byte[] b = new byte[2 + lens.Length + sendb.Length];
                //b[0] = command;
                //b[1] = (byte)lens.Length;
                //lens.CopyTo(b, 2);
                //sendb.CopyTo(b, 2 + lens.Length);
                byte[] b = MyGameClientHelper.CodingProtocol(command, text);

                int count = (b.Length <= 40960 ? b.Length / 40960 : (b.Length / 40960) + 1);
                if (count == 0)
                {
                    tcpClient.Client.Send(b);
                }
                else
                {
                    for (int i = 0; i < count; i++)
                    {
                        int zz = b.Length - (i * 40960) > 40960 ? 40960 : b.Length - (i * 40960);
                        byte[] temp = new byte[zz];
                        Array.Copy(b, i * 40960, temp, 0, zz);
                        tcpClient.Client.Send(temp);
                        //System.Threading.Thread.Sleep(1);
                        // Loom.WaitForNextFrame(10);
                        Loom.WaitForSeconds(0.001f);
                    }
                }
            }
            catch (Exception ee)
            {
                IsOnline = false;
                CloseConnect();
                if (TimeOutEvent != null)
                    TimeOutEvent();

                SendByteCheck(command, text);
                if (ErrorMessageEvent != null)
                    ErrorMessageEvent(9, "send:" + ee.Message);
                return false;
            }
            // tcpc.Close();

            return true;
        }


        #endregion



        /// <summary>
        /// 通过主线程执行方法避免跨线程UI问题
        /// </summary>
        public void OnTick()
        {
            if (mytemppakeList.Count > 0)
            {
                try
                {
                    TempPakeage str = mytemppakeList[0];
                    //xmhelper.Init(str.date, null);
                    //receiveServerEvent(str.command, str.date);

                }
                catch
                {
                }
                try
                {
                    mytemppakeList.RemoveAt(0);
                }
                catch { }
            }
            Debug.Log("队列中没有排队的方法需要执行。");
        }


        public void CloseConnect()
        {
            try
            {
                isok = false;

                IsOnline = false;
                //发送我要断开连接的消息
                this.SendRoot<int>((byte)CommandEnum.ClientSendDisConnected, "OneClientDisConnected", 0, 0);


                // receives_thread1.Abort();
                //checkToken_UpdateList_thread2.Abort();
               
                tcpClient.Close();
                AbortThread();

            }
            catch
            {
                Debug.Log("CloseConnect失败,发生异常");
            }
           

        }


        void AbortThread()
        {
            if (myThreadScheduler.isBusy) //线程在此期间没有完成工作Threaded work didn't finish in the meantime: time to abort.时间终止
            {
                Debug.Log("Terminate all worker Threads.");
                myThreadScheduler.AbortASyncThreads();

                Debug.Log("Terminate thread A & B.");
                if (threadA != null && threadA.IsAlive)
                    threadA.Interrupt();

                if (threadB != null && threadB.IsAlive)
                    threadB.Interrupt();
            }
            else
            {
                Debug.Log("Terminate thread A & B.");
                if (threadA != null && threadA.IsAlive)
                    threadA.Interrupt();

                if (threadB != null && threadB.IsAlive)
                    threadB.Interrupt();
            }

        }


        /// <summary>
        /// 接收到服务器发来的数据的处理方法
        /// </summary>
        /// <param name="obj"></param>
        void ReceiveData(object obj)
        {
            TempPakeage str = obj as TempPakeage;
            mytemppakeList.Add(str);
            if (ReceiveMessageEvent != null)
                ReceiveMessageEvent(str.command, str.date);

        }



        /// <summary>
        /// 线程启动的方法,初始化连接后要接收服务器发来的token,并更新
        /// </summary>
        void CheckToken_UpdateListDataThread()
        {
            while (isok)
            {
                // System.Threading.Thread.Sleep(10);
                // Loom.WaitForNextFrame(10);
                Loom.WaitForSeconds(0.01f);
                try
                {
                    int count = ListData.Count;
                    if (count > 0)
                    {
                        int bytesRead = ListData[0] != null ? ListData[0].Length : 0;
                        if (bytesRead == 0)
                            continue;
                        //如果到这里的continue内部,那么下面的代码不执行,重新到 --》 System.Threading.Thread.Sleep(10);开始
                        

                        byte[] tempbtye = new byte[bytesRead];
                        //解析消息体ListData,,
                        Array.Copy(ListData[0], tempbtye, tempbtye.Length);
                        // 检查tempbtye(理论上里面应该没有0x99,有方法已经处理掉了,但是可能会有)检测还有没有0x99开头的心跳包
                        _0x99:
                        if (tempbtye[0] == 0x99)
                        {
                            if (bytesRead > 1)
                            {
                                byte[] b = new byte[bytesRead - 1];
                                byte[] t = tempbtye;
                                //把心跳包0x99去掉
                                Array.Copy(t, 1, b, 0, b.Length);
                                ListData[0] = b;
                                tempbtye = b;
                                goto _0x99;
                            }
                            else
                            {   //说明只有1个字节,心跳包包头,无任何意思,那么直接删除
                                ListData.RemoveAt(0);
                                continue;
                            }
                        }

                        //ListData[0]第一个元素的长度 大于2
                        if (bytesRead > 2)
                        {
                            //第二段是固定一个字节,最高255,代表了第三段的长度
                            //这样第三段最高可以255*255位,这样表示数据内容的长度基本可以无限大了
                            // int a = tempbtye[1];
                            int part3_Length = tempbtye[1];
                            //tempbtye既是ListData[0]数据,
                            //第一位为command,指令
                            //第二位的数据是第三段的长度
                            //第三段的数据是第四段的长度
                            //第四段是内容数据
                            if (bytesRead > 2 + part3_Length)
                            {   //如果收到数据这段数据,大于
                                // int len = 0;
                                int part4_Length = 0;
                                if (s_datatype ==  SocketDataType.Bytes)
                                {
                                    byte[] bb = new byte[part3_Length];
                                    byte[] part4_LengthBitArray = new byte[part3_Length];

                                    //将tempbtye从第三位开始,复制数据到part4_LengthBitArray
                                    Array.Copy(tempbtye, 2, part4_LengthBitArray, 0, part3_Length);
                                    //len = ConvertToInt(bb);
                                    //获得实际数据的长度,也就是第四部分数据的长度
                                    part4_Length = MyGameClientHelper. ConvertToInt(part4_LengthBitArray);
                                }
                                else
                                {   //如果DataType不是DataType.bytes类型,,, 是Json类型
                                    //从某个Data中第三位开始截取数据,,获取第四段数据长度的字符串string
                                    String temp = System.Text.Encoding.UTF8.GetString(tempbtye, 2, part3_Length);
                                    String part4_Lengthstr = System.Text.Encoding.UTF8.GetString(tempbtye, 2, part3_Length);

                                    part4_Length = 0;
                                    //len = 0;
                                    //int part4_Lengthstrlength = 0;
                                    try
                                    {
                                        // len = int.Parse(temp);
                                        part4_Length = int.Parse(part4_Lengthstr);
                                        if (part4_Length == 0)  //len
                                        {   //如果第四段数据的长度为0 ,,,说明发的空消息,,没有第四段数据
                                            //如果第二位没有数据,,说明发的是空消息
                                            ListData.RemoveAt(0);
                                            continue;
                                        }
                                    }
                                    catch
                                    {
                                    }
                                }

                                try
                                {
                                    //如果计算出来的(2位数据位+第三段长度+第四度长度) 比当前ListData[0]长度还大...
                                    if ((part4_Length + 2 + part3_Length) > tempbtye.Length)
                                    {
                                        if (ListData.Count > 1)
                                        {
                                            //将第一个数据包删除
                                            ListData.RemoveAt(0);
                                            //重新读取第一个数据包(第二个数据包变为第一个)内容
                                            byte[] temps = new byte[ListData[0].Length];
                                            //将 数据表内容 拷贝到 temps中
                                            Array.Copy(ListData[0], temps, temps.Length);
                                            //新byte数组长度扩充,原数据长度 + (第二个)元素长度
                                            byte[] temps2 = new byte[tempbtye.Length + temps.Length];

                                            Array.Copy(tempbtye, 0, temps2, 0, tempbtye.Length);
                                            //将第一个元素ListData[0]完全从第一个地址开始 ,完全拷贝到 temps2数组中
                                            Array.Copy(temps, 0, temps2, tempbtye.Length, temps.Length);
                                            //将第二个元素拼接到temps2中,从刚复制数据的最后一位 +1 开始
                                            ListData[0] = temps2;
                                            //最后将更新数据包里面的 第一个元素为新元素
                                        }
                                        else
                                        {
                                            //  System.Threading.Thread.Sleep(20);
                                            // Loom.WaitForNextFrame(10);
                                            Loom.WaitForSeconds(0.02f);
                                        }
                                        continue;
                                    }
                                    else if (tempbtye.Length > (part4_Length + 2 + part3_Length))
                                    {
                                        //如果 数据包长度 比  计算出来的(2位数据位+第三段长度+第四度长度)  还大 
                                        //考虑大出的部分
                                        int currentAddcount = (part4_Length + 2 + part3_Length);
                                        int offset_length = tempbtye.Length - currentAddcount;
                                        byte[] temps = new byte[offset_length];


                                        //Array.Copy(tempbtye, (part4_Length + 2 + part3_Length), temps, 0, temps.Length);
                                        Array.Copy(tempbtye, currentAddcount, temps, 0, temps.Length);
                                        //把当前ListData[0]中 后面的数据,复制到 temps数组中...

                                        ListData[0] = temps;
                                    }
                                    else if (tempbtye.Length == (part4_Length + 2 + part3_Length))
                                    {   //长度刚好匹配
                                        ListData.RemoveAt(0);
                                    }
                                }
                                catch (Exception e)
                                {
                                    if (ErrorMessageEvent != null)
                                        ErrorMessageEvent(3, e.StackTrace + "unup001:" + e.Message + "2 + a" + 2 + part3_Length + "---len" + part4_Length + "--tempbtye" + tempbtye.Length);
                                }

                                try
                                {
                                    if (s_datatype ==  SocketDataType.Json)
                                    {
                                        //读取出第四部分数据内容,,
                                        string temp = System.Text.Encoding.UTF8.GetString(tempbtye, 2 + part3_Length, part4_Length);
                                        TempPakeage str = new TempPakeage();
                                        str.command = tempbtye[0];
                                        //命令等于第一位 
                                        str.date = temp;
                                        //服务器发来执行是0xff,说明发送的是token指令
                                        if (tempbtye[0] == 0xff)
                                        {
                                            if (temp.IndexOf("token") >= 0)
                                                tokan = temp.Split('|')[1];

                                            //用单个字符来分隔字符串,并获取第二个元素,,
                                            //这里因为服务端发来的token后面跟了一个|字符
                                            else if (temp.IndexOf("jump") >= 0)
                                            {
                                                //0xff就是指服务器满了
                                                tokan = "连接数量满";
                                                if(JumpServerEvent!=null)
                                                JumpServerEvent(temp.Split('|')[1]);
                                            }
                                            else
                                            {  // 当上面条件都不为真时执行 ,如果虽然指令是0xff,但是不包含token或jump
                                                ReceiveData(str);

                                            }
                                        }
                                        else if (ReceiveMessageEvent != null)
                                        {
                                            //如果tempbtye[0] == 0xff 表示token,不等的情况
                                            ReceiveData(str);

                                        }
                                    }
                                    //if (DT == DataType.bytes)
                                    //{

                                    //    byte[] bs = new byte[len - 2 + a];
                                    //    Array.Copy(tempbtye, bs, bs.Length);
                                    //    temppake str = new temppake();
                                    //    str.command = tempbtye[0];
                                    //    str.datebit = bs;
                                    //    rec(str);

                                    //}
                                    continue;
                                }
                                catch (Exception e)
                                {
                                    if (ErrorMessageEvent != null)
                                        ErrorMessageEvent(3, e.StackTrace + "unup122:" + e.Message);
                                }
                            }
                        }
                        else
                        {   // //ListData[0]第一个元素的Length 不大于2 ,,  
                            if (tempbtye[0] == 0)
                                ListData.RemoveAt(0);
                        }
                    }
                }
                catch (Exception e)
                {
                    if (ErrorMessageEvent != null)
                        ErrorMessageEvent(3, "unup:" + e.Message + "---" + e.StackTrace);
                    try
                    {
                        ListData.RemoveAt(0);
                    }
                    catch { }
                }
            }
        }

        /// <summary>
        /// 线程启动的方法
        /// </summary>
        /// <param name="obj"></param>
        void ReceivesThread(object obj)
        {
            while (isok)
            {
                //System.Threading.Thread.Sleep(50);
                // Loom.WaitForNextFrame(10);
                Loom.WaitForSeconds(0.05f);
                try
                {
                    //可以用TcpClient的Available属性判断接收缓冲区是否有数据,来决定是否调用Read方法
                    int bytesRead = tcpClient.Client.Available;
                    if (bytesRead > 0)
                    {
                        //缓冲区
                        byte[] tempbtye = new byte[bytesRead];
                        try
                        {
                            timeout = DateTime.Now;
                            //从绑定接收数据 Socket 到接收缓冲区中
                            tcpClient.Client.Receive(tempbtye);
                            _0x99:
                            if (tempbtye[0] == 0x99)
                            {   //如果缓冲区第一个字符是 0x99心跳包指令
                                timeout = DateTime.Now;
                                //记录现在的时间
                                if (tempbtye.Length > 1)
                                {
                                    //去掉第一个字节,长度总体减去1个,
                                    byte[] b = new byte[bytesRead - 1];
                                    try
                                    {
                                        //复制 Array 中的一系列元素(从指定的源索引开始),
                                        //并将它们粘贴到另一 Array 中(从指定的目标索引开始)
                                        //原始 Array 为tempbtye,原始Array的初始位置
                                        //另外一个 目标 Array , 开始位置为0,长度为b.Length
                                        Array.Copy(tempbtye, 1, b, 0, b.Length);
                                        //那么b中的到的就是去掉心跳包指令0x99以后的后面的数据
                                    }
                                    catch { }
                                    tempbtye = b;
                                    //反复执行去掉,心跳包,,,
                                    goto _0x99;
                                }
                                else
                                    continue;

                                //后面的不执行了,回调到 上面的while循环开始 重新执行...
                            }


                        }
                        catch (Exception ee)
                        {
                            if(ErrorMessageEvent!=null)
                                ErrorMessageEvent(22, ee.Message);
                        }
                        //lock (this)

                        //{
                        //将接收到的 非心跳包数据加入到 ListData中
                        ListData.Add(tempbtye);
                        // }

                    }

                    //线程每隔指定的过期时间秒,判定,如果没有数据发送过来,,,tcpc.Client.Available=0 情况下
                    else
                    {
                        try
                        {
                            TimeSpan ts = DateTime.Now - timeout;
                            if (ts.TotalSeconds > mytimeout)
                            {  //判断时间过期
                                IsOnline = false;
                                CloseConnect();
                                //isreceives = false;

                                if (TimeOutEvent != null)
                                    TimeOutEvent();

                                if (ErrorMessageEvent != null)
                                    ErrorMessageEvent(2, "连接超时,未收到服务器指令");
                                continue;
                            }
                        }
                        catch (Exception ee)
                        {
                            if (ErrorMessageEvent != null)
                                ErrorMessageEvent(21, ee.Message);
                        }
                    }
                }
                catch (Exception e)
                {
                    if (ErrorMessageEvent != null)
                        ErrorMessageEvent(2, e.Message);
                }
            }
        }

    }
}



帮助类



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyTcpClient
{
  

    public delegate void ReceiveMessage(byte command, String text);
    public delegate void ReceiveBit(byte command, byte[] data);

    public delegate void ConnectOk();

    public delegate void TimeOut();

    public delegate void JumpServer(string jtext);


    public delegate void ErrorMessage(int type, string error);


    public enum SocketDataType { Json, Bytes };

    public class TempPakeage
    {
        public byte command { get; set; }
        public string date { get; set; }
        public byte[] datebit { get; set; }
    }


    public static class MyGameClientHelper
    {


        public static int ConvertToInt(byte[] list)
        {
        int ret = 0;
        int i = 0;
        foreach (byte item in list)
        {
            ret = ret + (item << i);
            i = i + 8;
        }
        return ret;

        }

        public static byte[] ConvertToByteList(int v)
        {
        List<byte> ret = new List<byte>();
        int value = v;
        while (value != 0)
        {
            ret.Add((byte)value);
            value = value >> 8;
        }
        byte[] bb = new byte[ret.Count];
        ret.CopyTo(bb);
        return bb;

        }

        /// <summary>
        /// 对数据进行编码,第1位为命名位,第2位为第三位的数据长度,第三部分为第四部分的数据长度,第四部分为实际数据
        /// </summary>
        /// <param name="command"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public static byte[] CodingProtocol(byte command, string text)
        {
            byte[] sendb = System.Text.Encoding.UTF8.GetBytes(text);
            byte[] part3_length = System.Text.Encoding.UTF8.GetBytes(sendb.Length.ToString());
            byte[] b = new byte[2 + part3_length.Length + sendb.Length];
            b[0] = command;
            b[1] = (byte)part3_length.Length;
            part3_length.CopyTo(b, 2);
            //扩充 第四部分数据(待发送的数据)的长度,扩充到b数组第三位开始的后面
            sendb.CopyTo(b, 2 + part3_length.Length);
            //扩充 第四部分数据实际的数据,扩充到b数组第三部分结尾后面...

            return b;
        }


        /// <summary>
        /// 对数据进行编码,第1位为命名位,第2位为第三位的数据长度,第三部分为第四部分的数据长度,第四部分为实际数据
        /// </summary>
        /// <param name="command"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public static byte[] CodingProtocol(byte command, byte[] text)
        {
            byte[] sendb = text;
            byte[] part3_length = System.Text.Encoding.UTF8.GetBytes(sendb.Length.ToString());
            byte[] b = new byte[2 + part3_length.Length + sendb.Length];
            b[0] = command;
            b[1] = (byte)part3_length.Length;
            part3_length.CopyTo(b, 2);
            //扩充 第四部分数据(待发送的数据)的长度,扩充到b数组第三位开始的后面
            sendb.CopyTo(b, 2 + part3_length.Length);
            //扩充 第四部分数据实际的数据,扩充到b数组第三部分结尾后面...

            return b;
        }


        public static void CheckHeartPackage_0x99(int bytesRead,byte[] tempbtye)
        {
            
        }

    }

}



MainClient单例类



using UnityEngine;
using System.Collections;
using GDGeek;
using MyTcpClient;
using System;
using UnityEngine.SceneManagement;
using WeaveBase;
using MyTcpCommandLibrary;
using UnityEngine.Events;
using MyTcpCommandLibrary.Model;

public class MainClient : Singleton<MainClient>
{


    public WeaveSocketGameClient weaveSocketGameClient;

    public ServerBackLoginEvent serverBackLoginEvent =new ServerBackLoginEvent();

  
    public SetLoginTempModelEvent setLoginTempModelEvent = new SetLoginTempModelEvent();

    public SetGameScoreTempModelEvent setGameScoreTempModelEvent = new SetGameScoreTempModelEvent();

    public FirstCheckServerEvent firstCheckServerEvent = new FirstCheckServerEvent();

    public GameScoreTempModel GameScore;

    public LoginTempModel loginUserModel;
    // Use this for initialization
    void Start()
    {
        DontDestroyOnLoad(this);
        setLoginTempModelEvent.AddListener(SetLoginModel);


    }
    public string receiveMessage;

    public void InvokeSetLoginTempModelEvent(LoginTempModel _model)
    {
        setLoginTempModelEvent.Invoke(_model);
    }
    GameScoreTempModel tempGameScore;
    public void CallSetGameScoreTempModelEvent(GameScoreTempModel gsModel)
    {
        // StartCoroutine(CallSetGameScoreEvent(gsModel));
        tempGameScore = gsModel;
    }

    IEnumerator CallSetGameScoreEvent(GameScoreTempModel gsModel)
    {
        yield return new WaitForSeconds(0.5f);
        setGameScoreTempModelEvent.Invoke(gsModel);
    }


    // Update is called once per frame
    void Update()
    {
        //if (receiveMessage.Length != 0)
        //{
        //    receiveMessage = string.Empty;
        //}
        if (canLoadSceneFlag)
        {
            LoadGameScene();
            canLoadSceneFlag = false;
        }


        if (weaveSocketGameClient != null)
            weaveSocketGameClient.OnTick();



        if(tempGameScore != null)
        {
            StartCoroutine(CallSetGameScoreEvent(tempGameScore));
            tempGameScore = null;
        }
    }

    public void ConnectToServer(string serverIp,int port)
    {
        try
        {
            weaveSocketGameClient = new WeaveSocketGameClient(SocketDataType.Json);
            weaveSocketGameClient.ConnectOkEvent += OnConnectOkEvent;
            weaveSocketGameClient.ReceiveMessageEvent += OnReceiveMessageEvent;
            weaveSocketGameClient.ErrorMessageEvent += OnErrorMessageEvent;
            weaveSocketGameClient.ReceiveBitEvent += OnReceiveBitEvent;
            weaveSocketGameClient.TimeOutEvent += OnTimeOutEvent;

            //pcp2.AddListenClass(new MyClientFunction());
            Debug.Log("初始化OK");
            //bool bb = pcp2.start("61.184.86.126", 10155, false);
            // bool bb = weaveSocketGameClient.StartConnect("61.184.86.126", 10155, 30, false);
            bool bb = weaveSocketGameClient.StartConnect(serverIp, port, 30, false);
            Debug.Log("链接OK");
             firstCheckServerEvent.Invoke(bb);
        }
        catch
        {
            firstCheckServerEvent.Invoke(false);
        }

    }

    void CallServerFunc()
    {
        try
        {
            //weaveSocketGameClient.SendRoot<int>(0x02, "login", 11111, 0);
            //在加个发送
            weaveSocketGameClient.tokan = "UnityTokan";
            weaveSocketGameClient.SendRoot<int>(0x01, "getnum", 0, 0);
            //调用服务端方法getnum,是服务端的方法。
            //这样就可以了,我们试试
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }

    private void OnTimeOutEvent()
    {
        Debug.Log("连接超时");
        //throw new NotImplementedException();
    }

    private void OnReceiveBitEvent(byte command, byte[] data)
    {
        Debug.Log("收到了Bit数据");
        // throw new NotImplementedException();
    }

    private void OnErrorMessageEvent(int type, string error)
    {
        Debug.Log("发生了错误");
        //throw new NotImplementedException();
    }

    private void OnReceiveMessageEvent(byte command, string text)
    {
        // throw new NotImplementedException();
        Debug.Log("收到了新数据");

        //throw new NotImplementedException();
        receiveMessage = "指令:" + command + ".内容:" + text;
        Debug.Log("原始数据是:" + receiveMessage);
        try
        {
            WeaveSession ws = Newtonsoft.Json.JsonConvert.DeserializeObject<WeaveSession>(text);
            Debug.Log("接受到的WeaveSession数据是:" + ws.Request + " " + ws.Root);
        }
        catch
        {
            Debug.Log("Json转换对象出错了");
        }
       // receiveMessage = "指令:" + command + ".内容:" + text;
        Debug.Log("收到的信息是:" + receiveMessage);
        ICheckServerMessageFactory factory = CheckCommand.CheckCommandType(command);

        ICheckServerMessage checkSmsg = factory.CheckServerMessage();
        checkSmsg.CheckServerMessage(text);

    }

    private void OnConnectOkEvent()
    {
        Debug.Log("已经连接成功");
    }

   

    private void StopConnect()
    {
        if (weaveSocketGameClient != null)
        {

            weaveSocketGameClient.CloseConnect();
            weaveSocketGameClient.ConnectOkEvent -= OnConnectOkEvent;
            weaveSocketGameClient.ReceiveMessageEvent -= OnReceiveMessageEvent;
            weaveSocketGameClient.ErrorMessageEvent -= OnErrorMessageEvent;
            weaveSocketGameClient.ReceiveBitEvent -= OnReceiveBitEvent;
            weaveSocketGameClient.TimeOutEvent -= OnTimeOutEvent;

            // weaveSocketGameClient = null;

        }

    }



    public  void SendLogin(LoginTempModel user )
    {
        try
        {

            // weaveSocketGameClient.SendRoot<LoginTempModel>((byte)CommandEnum.ClientSendLoginModel, "CheckLogin", user, 0);
            StartCoroutine(  WaitSendLogin(user)  );
            Debug.Log("SendLoginFunc");
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }

    IEnumerator WaitSendLogin(LoginTempModel user)
    {
        yield return new WaitForSeconds(0.2f);
        weaveSocketGameClient.SendRoot<LoginTempModel>((byte)CommandEnum.ClientSendLoginModel, "CheckLogin", user, 0);
    }

    public void SendCheckUserScore()
    {
        try
        {
            LoginTempModel user = loginUserModel;
            // weaveSocketGameClient.Tokan = "UnityTokan";
            // weaveSocketGameClient.SendRoot<int>(0x01, "getnum", 0, 0);

            weaveSocketGameClient.SendRoot<LoginTempModel>((byte)CommandEnum.ClientSendGameScoreModel, "GetUserScore", user, 0);
            Debug.Log("SendLoginFunc");
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }


    public void SendNewScoreUpdate(int _score,int _missed)
    {
        try
        {
            GameScoreTempModel gsModel = new GameScoreTempModel()
            {
                userName = loginUserModel.userName,
                missenemy = _missed,
                score = _score
            };
            //LoginTempModel user = loginUserModel;
            // weaveSocketGameClient.Tokan = "UnityTokan";
            // weaveSocketGameClient.SendRoot<int>(0x01, "getnum", 0, 0);

            weaveSocketGameClient.SendRoot<GameScoreTempModel>((byte)CommandEnum.ClientSendGameScoreModel, "UpdateScore", gsModel, 0);
            Debug.Log("UpdateScore");
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }




    public int sceneIndex;
    public bool canLoadSceneFlag;
     void LoadGameScene()
    {
        SceneManager.LoadScene(1);
    }


    public void SetLoadSceneFlag()
    {
        canLoadSceneFlag = true;
    }

    void OnDestroy()
    {
        //SetLoginModelEvent.RemoveListener(SetLoginModel);

    }

    private void SetLoginModel(LoginTempModel _model)
    {
        loginUserModel = _model;
    }

    private void OnApplicationQuit()
    {
        StopConnect();
    }



}


public class SetLoginTempModelEvent : UnityEvent<LoginTempModel> { }

public class SetGameScoreTempModelEvent : UnityEvent<GameScoreTempModel> { }

public class ServerBackLoginEvent : UnityEvent<bool>{}

public class FirstCheckServerEvent : UnityEvent<bool> { }

登陆界面类



using MyTcpCommandLibrary.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class LoginHandler : MonoBehaviour {


    public InputField input_Username;
    public InputField input_Password;
    
    public InputField input_ServerIP;
    public InputField input_ServerPort;


    public Text server_msg_text;
    public Button login_button;

    // public LoginModel userModel;
    // Use this for initialization
    void Start() {
        MainClient.Instance.serverBackLoginEvent.AddListener(GetServerBackLoginEvent);

        MainClient.Instance.firstCheckServerEvent.AddListener(firstCheckServerConfigEvent);
    }

    private void firstCheckServerConfigEvent(bool connectToServerResult)
    {
        // throw new NotImplementedException();
        connectedServerOK = connectToServerResult;
    }

    public void SetServerIP_Connected()
    {
        string ip = input_ServerIP.text;
        int port = int.Parse(input_ServerPort.text);

        if(connectedServerOK ==false)
        MainClient.Instance.ConnectToServer(ip, port);
    }


    private void GetServerBackLoginEvent(bool arg0)
    {
        //throw new NotImplementedException();
        server_msg = "登陆失败,账号密码错误...";
       

    }

    public bool connectedServerOK = false;

    public void Login()
    {

        LoginTempModel model = new LoginTempModel()
        {
            userName = input_Username.text,
            password = input_Password.text,
            //userName = "ssss",
            //password = "yyyyyy",
            logintime = System.DateTime.Now.ToString("yyyyMMddHHmmssfff")
        };
       // userModel = model;
        MainClient.Instance.InvokeSetLoginTempModelEvent(model);
        MainClient.Instance.SendLogin(model);

    }

    private string server_msg = "";

    public void SetServerMsgShow(string serverMsg)
    {
        server_msg_text.text = serverMsg;
    }

    void OnDestroy()
    {
        MainClient.Instance.serverBackLoginEvent.RemoveListener(GetServerBackLoginEvent);

        MainClient.Instance.firstCheckServerEvent.RemoveListener(firstCheckServerConfigEvent);

    }





    // Update is called once per frame
    void Update () {
		if( string.IsNullOrEmpty( server_msg) ==false || server_msg.Length >2)
        {
            SetServerMsgShow(server_msg);
            login_button.gameObject.SetActive(true);
            server_msg = "";
        }
	}
}




游戏场景界面UI控制显示类

using UnityEngine;
using System.Collections;

using UnityEngine.Events;
using UnityEngine.UI;
using System;
using MyTcpCommandLibrary.Model;

public class GameScoreHandler : MonoBehaviour
{

    public static UpdateScoreEvent updateScoreEvent = new UpdateScoreEvent();
    public static UpdateLivesEvent updateLivesEvent = new UpdateLivesEvent();
    public static UpdateMissedEvent updateMissedEvent = new UpdateMissedEvent();

    public static UnityEvent SendUpdateScoreEvent = new UnityEvent();
   // public static UnityEvent<GameScoreTempModel> SetGameScoreUI;



    public Text userNameText;
    public Text now_scoreText;
    public Text now_livesText;
    public Text now_missedText;
    public Text serverText;
    
    public Text last_scoreText;
    public Text last_missedText;

    // Use this for initialization
    void Start()
    {
        updateScoreEvent.AddListener( OnUpdateScore);
        updateLivesEvent.AddListener(OnUpdateLives);
        updateMissedEvent.AddListener(OnUpdateMissed);
        SendUpdateScoreEvent.AddListener(OnSendUpdateScore);
        MainClient.Instance.setGameScoreTempModelEvent.AddListener(SetLastData);

    }

    private void OnSendUpdateScore()
    {
        //throw new NotImplementedException();
        serverText.text = "积分已发往服务器...";
    }

    private void OnUpdateScore(int _score)
    {
       
        now_scoreText.text = "积分:" + _score.ToString();
       
    }
    void OnDestory()
    {

        updateScoreEvent.RemoveListener(OnUpdateScore);
        updateLivesEvent.RemoveListener(OnUpdateLives);
        updateMissedEvent.RemoveListener(OnUpdateMissed);
        SendUpdateScoreEvent.RemoveListener(OnSendUpdateScore);
        MainClient.Instance.setGameScoreTempModelEvent.RemoveListener(SetLastData);


    }
    private void OnUpdateLives(int _lives)
    {
        now_livesText.text = "生命:" + _lives.ToString();
       
    }

    private void OnUpdateMissed(int _missed)
    {
       
        now_missedText.text = "放走敌人:" + _missed.ToString();
    }

    private void OnDestroy()
    {

    }

    public void SetUserNameData(string _uname)
    {
        userNameText.text = _uname;
    }



    public void SetLastData(GameScoreTempModel gsModel)
    {
        //userNameText.text = "生命:" + gsModel.userName;
        //last_scoreText.text = "积分:" + gsModel.score.ToString();
        //last_missedText.text = "放走敌人:" + gsModel.missenemy.ToString();
        tempScore = gsModel;
    }

    public void SetLastDataText()
    {
        userNameText.text = "生命:" + tempScore.userName;
        last_scoreText.text = "积分:" + tempScore.score.ToString();
        last_missedText.text = "放走敌人:" + tempScore.missenemy.ToString();
    }

    public void SetNowDate(int _lives, int _lastScore, int _lastMissed)
    {
        now_livesText.text ="生命:"+ _lives.ToString();
        now_scoreText.text = "积分:" + _lastScore.ToString();
        now_missedText.text = "放走敌人:" + _lastMissed.ToString();
    }

    GameScoreTempModel tempScore;
    // Update is called once per frame
    void Update()
    {
        if(tempScore != null)
        {
            SetLastDataText();
            tempScore = null;
        }
    }

    public void ReloadGameScene()
    {
        //跳转场景
        MainClient.Instance.SetLoadSceneFlag();


        //发送读取上次分数数据的逻辑
        MainClient.Instance.SendCheckUserScore();
    }


}
public class UpdateScoreEvent: UnityEvent<int> { }
public class UpdateLivesEvent : UnityEvent<int> { }
public class UpdateMissedEvent : UnityEvent<int> { }



客户端使用的主要代码为


WeaveSocketGameClient  weaveSocketGameClient = new WeaveSocketGameClient(SocketDataType.Json);
weaveSocketGameClient.ConnectOkEvent += OnConnectOkEvent;
weaveSocketGameClient.ReceiveMessageEvent += OnReceiveMessageEvent;
weaveSocketGameClient.ErrorMessageEvent += OnErrorMessageEvent;
weaveSocketGameClient.ReceiveBitEvent += OnReceiveBitEvent;
weaveSocketGameClient.TimeOutEvent += OnTimeOutEvent;
 Debug.Log("初始化OK");
 bool bb = weaveSocketGameClient.StartConnect(serverIp, port, 30, false);
 Debug.Log("链接OK");
 //触发第一次 检查并连接服务器状态事件,用于通知其它Unity脚本,作出相应反应
  firstCheckServerEvent.Invoke(bb);


没什么可说的,代码已经很明确了,常用的几个事件都有,,


具体说一下MainClient类里面的  接收数据处理用的抽象工厂

在接收事件处理方法里面写有如下代码


        Debug.Log("收到了新数据");

   
        receiveMessage = "指令:" + command + ".内容:" + text;
        Debug.Log("原始数据是:" + receiveMessage);
        try
        {
            WeaveSession ws = Newtonsoft.Json.JsonConvert.DeserializeObject<WeaveSession>(text);
            Debug.Log("接受到的WeaveSession数据是:" + ws.Request + " " + ws.Root);
        }
        catch
        {
            Debug.Log("Json转换对象出错了");
        }
        Debug.Log("收到的信息是:" + receiveMessage);
         //根据收到的指令来确定要生成的工厂
        ICheckServerMessageFactory factory = CheckCommand.CheckCommandType(command);
        //调用对应工厂,生成具体的接口实现类
        ICheckServerMessage checkSmsg = factory.CheckServerMessage();
        //调用具体接口类的 处理数据的具体方法
        checkSmsg.CheckServerMessage(text);



抽象工厂以及相关代码如下


帮助类,也可直接写成Switch,这里避免代码过长,所以封装了一下

using UnityEngine;
using System.Collections;

public static class CheckCommandHelper 
{
    public static ICheckServerMessageFactory SwitchCheckCommand(byte command)
    {
        ICheckServerMessageFactory factory = null;
        switch (command)
        {
            case (0x1):
                factory = new LoginMessageFactory();
                break;
            case (0x2):
                factory = new GameScoreMessageFactory();
                break;
                //其他类型略;
        }
        return factory;
    }
    
}

工厂接口

using System;

public interface ICheckServerMessageFactory
{

    ICheckServerMessage CheckServerMessage();
   
}

数据处理接口


using System;



public interface ICheckServerMessage
{

    void CheckServerMessage( string text);

}



具体实现类


using UnityEngine;
using System.Collections;
using System;
using WeaveBase;
public class LoginMessage : ICheckServerMessage
{
    public void CheckServerMessage( string text)
    {
       // throw new NotImplementedException();
       WeaveSession ws = Newtonsoft.Json.JsonConvert.DeserializeObject<WeaveSession>(text);
        Debug.Log("收到的消息是:"+text);
        if(ws.Request == "ServerBackLoginResult" )
        {
            if( ws.GetRoot<bool>() == true)
            {
                //如果登陆成功,,处理的逻辑......
                //先更新用户

                //跳转场景
                MainClient.Instance.SetLoadSceneFlag();


                //发送读取上次分数数据的逻辑
                MainClient.Instance.SendCheckUserScore();
            }
           
            else
            {
                MainClient.Instance.serverBackLoginEvent.Invoke(false);
            }
        }
       

    }

}


-------------------------------------------------------------------



using UnityEngine;
using System.Collections;
using System;
using WeaveBase;
using MyTcpCommandLibrary.Model;

public class GameScoreMessage : ICheckServerMessage
{
    public void CheckServerMessage(string text)
    {
        // throw new NotImplementedException();
        WeaveSession ws = Newtonsoft.Json.JsonConvert.DeserializeObject<WeaveSession>(text);
        Debug.Log("收到的GameScoreMessage消息是:" + text);
        if (ws.Request == "ServerSendGameScore")
        {
            GameScoreTempModel gsModel = ws.GetRoot<GameScoreTempModel>();
            if (gsModel != null )
            {

                MainClient.Instance.CallSetGameScoreTempModelEvent(gsModel);
              
            }

            else
            {
               // MainClient.Instance.serverBackLoginEvent.Invoke(false);
            }
        }

    }
}




-----------------------------------------------------------------------



工厂

using UnityEngine;
using System.Collections;
using System;

public class LoginMessageFactory : ICheckServerMessageFactory
{
    public ICheckServerMessage CheckServerMessage()
    {
        //throw new NotImplementedException();
        return new LoginMessage();
    }
}





--------------------------------------------------------


using UnityEngine;
using System.Collections;

public class GameScoreMessageFactory : ICheckServerMessageFactory
{
    public ICheckServerMessage CheckServerMessage()
    {
        //throw new NotImplementedException();
        return new GameScoreMessage();
    }
}




命令的枚举


using System;


namespace MyTcpCommandLibrary
{
    public enum CommandEnum :byte
    {
        /// <summary>
        /// 
        /// </summary>
        ClientSendLoginModel = 0x02,

        ClientSendGameScoreModel = 0x03,

        ServerSendLoginResult = 0x04,

       // ServerSendGameScoreModel = 0x05,

        ClientSendDisConnected = 0x06,

        ServerSendUpdateGameScoreResult = 0x07,


        ClientSendCheckScore = 0x08,

        ServerSendGetGameScoreResult = 0x09

    }
}



-------------------------------------------

让我们再次来理一理客户端逻辑

-------------------------------------------


----------------------------------------------

启动程序

----------------------------------------------

玩家输入账号密码

----------------------------------------------

点击登陆按钮,

----------------------------------------------

调用MainClient里面的ConnectToServer 方法 

----------------------------------------------

连接服务器(如果成功),继续发送账号密码到服务器的命令

----------------------------------------------

再调用MainClient里面的 SendLogin  方法(有个等待0.2秒)


----------------------------------------------

服务器接收账号密码,进行查找数据库操作

----------------------------------------------

调用了MyTcpCommandLibrary项目中的LoginManageCommand类的CheckLogin方法(具体LiteDB操作数据的代码不再细说,源码一看就明白了)


 [InstallFun("forever")]
        public void CheckLogin(Socket soc, WeaveSession wsession)
        {

            // string jsonstr = _0x01.Getjson();
            LoginTempModel get_client_Send_loginModel = wsession.GetRoot<LoginTempModel>();



            //执行查找数据的操作......
            bool loginOk = false;


            AddSystemData();

            loginOk = CheckUserCanLoginIn(get_client_Send_loginModel);
            if (loginOk)
            {
                // UpdatePlayerListSetOnLine  发送有玩家成功登陆服务器事件,用于通知前端更新UserListBox 
                ServerLoginOKEvent(get_client_Send_loginModel.userName, soc);


            }
            SendRoot<bool>(soc, (byte)CommandEnum.ServerSendLoginResult, "ServerBackLoginResult", loginOk , 0, wsession.Token);
            //发送人数给客户端
            //参数1,发送给客户端对象,参数2,发送给客户端对应的方法,参数3,人数的实例,参数4,此处无作用,参数5,客户端此次token
        }


----------------------------------------------

发送查找结果给客户端......

----------------------------------------------

如果客户端接收到服务器发过来的登陆成功消息(跳转到游戏场景),

----------------------------------------------

数据处理工厂接收到命令调用LoginMessageFactory,并返回一个具体的ICheckServerMessage接口实现类LoginMessage

----------------------------------------------

调用它的CheckServerMessage方法

-----------------------------------------------

using UnityEngine;
using System.Collections;
using System;
using WeaveBase;
public class LoginMessage : ICheckServerMessage
{
    public void CheckServerMessage( string text)
    {
       // throw new NotImplementedException();
       WeaveSession ws = Newtonsoft.Json.JsonConvert.DeserializeObject<WeaveSession>(text);
        Debug.Log("收到的消息是:"+text);
        if(ws.Request == "ServerBackLoginResult" )
        {
            if( ws.GetRoot<bool>() == true)
            {
                //如果登陆成功,,处理的逻辑......
                //先更新用户

                //跳转场景
                MainClient.Instance.SetLoadSceneFlag();


                //发送读取上次分数数据的逻辑
                MainClient.Instance.SendCheckUserScore();
            }
           
            else
            {
                MainClient.Instance.serverBackLoginEvent.Invoke(false);
            }
        }
       

    }

}



----------------------------------------------

如果返回失败,那么提示账号密码错误

----------------------------------------------

客户端再次发送查找当前用户的历史积分数据的命令

----------------------------------------------

既是上面代码中的//发送读取上次分数数据的逻辑
MainClient.Instance.SendCheckUserScore();方法里面已经封装了用户的UserName

具体方法代码是


LoginTempModel user = loginUserModel;
          
weaveSocketGameClient.SendRoot<LoginTempModel>((byte)CommandEnum.ClientSendGameScoreModel, "GetUserScore", user, 0);


----------------------------------------------

(正在游戏场景运行中)

----------------------------------------------

客户端接受到历史积分数据,并更新显示到UnityUI界面上

----------------------------------------------

同上..................调用实现接口ICheckServerMessage的具体类GameScoreMessage的CheckServerMessage方法


----------------------------------------------

using UnityEngine;
using System.Collections;
using System;
using WeaveBase;
using MyTcpCommandLibrary.Model;

public class GameScoreMessage : ICheckServerMessage
{
    public void CheckServerMessage(string text)
    {
        // throw new NotImplementedException();
        WeaveSession ws = Newtonsoft.Json.JsonConvert.DeserializeObject<WeaveSession>(text);
        Debug.Log("收到的GameScoreMessage消息是:" + text);
        if (ws.Request == "ServerSendGameScore")
        {
            GameScoreTempModel gsModel = ws.GetRoot<GameScoreTempModel>();
            if (gsModel != null )
            {
                //触发收到服务器发送来的积分数据的事件,并更新到前端UI显示上
                MainClient.Instance.CallSetGameScoreTempModelEvent(gsModel);
              
            }

            else
            {
               // MainClient.Instance.serverBackLoginEvent.Invoke(false);
            }
        }

    }
}



----------------------------------------------

P0-玩家战机生命为0时,向服务器发送本次游戏积分数据

----------------------------------------------


调用MainClient里面的SendNewScoreUpdate方法

----------------------------------------------

 public void SendNewScoreUpdate(int _score,int _missed)
    {
        try
        {
            GameScoreTempModel gsModel = new GameScoreTempModel()
            {
                userName = loginUserModel.userName,
                missenemy = _missed,
                score = _score
            };
            //LoginTempModel user = loginUserModel;
            // weaveSocketGameClient.Tokan = "UnityTokan";
            // weaveSocketGameClient.SendRoot<int>(0x01, "getnum", 0, 0);

            weaveSocketGameClient.SendRoot<GameScoreTempModel>((byte)CommandEnum.ClientSendGameScoreModel, "UpdateScore", gsModel, 0);
            Debug.Log("UpdateScore");
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }



----------------------------------------------

服务器收到玩家本次游戏积分数据,进行数据库更新操作(根据用户名)

----------------------------------------------

调用了MyTcpCommandLibrary项目中的GameScoreCommand类的UpdateScore方法(具体LiteDB操作数据的代码不再细说,源码一看就明白了)

----------------------------------------------

   [InstallFun("forever")]
        public void UpdateScore(Socket soc, WeaveSession wsession)
        {
             GameScoreTempModel gsModel = wsession.GetRoot<GameScoreTempModel>();
          

            //执行数据更新的操作......
            bool updateSocreResult = UpdateUserScore(gsModel.userName, gsModel.score , gsModel.missenemy);
            
            if (updateSocreResult)
            {
                // 向客户端发送 更新积分成功的信息
                SendRoot<bool>(soc, (byte)CommandEnum.ServerSendUpdateGameScoreResult, "ServerSendUpdateGameScoreResult", updateSocreResult, 0, wsession.Token);

            }
            else
            {
                // 向客户端发送 更新积分失败的信息
                SendRoot<bool>(soc, (byte)CommandEnum.ServerSendUpdateGameScoreResult, "ServerSendUpdateGameScoreResult", updateSocreResult, 0, wsession.Token);
                //发送人数给客户端
                //参数1,发送给客户端对象,参数2,发送给客户端对应的方法,参数3,人数的实例,参数4,此处无作用,参数5,客户端此次token
            }
        }



----------------------------------------------

客户端显示一个按钮,玩家可点击再玩一次,再次游戏(跳转P0,当玩家生命为0时)


----------------------------------------------


GameScoreHandler类的ReloadGameScene方法,发送本次游戏积分数据并重新加载游戏场景



---------------------------------------


其它的Unity3D游戏逻辑代码在这里不再细说








WeaveSocket官方QQ群17375149 
  



本节到此结束,未完待续












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值