Unity太空大戰遊戲-Socket網絡通訊教學示例

項目下載地址前端

https://gitee.com/dreamsfly900/universal-Data-Communication-System-for-windowsgit

 Example /Unity3D_2DShootServer_Client 項目文件位置。數據庫

教程編寫有 SuperLinMeng 提供,QQ:2360450496json

WeaveSocket通信框架官方QQ羣17375149windows

WeaveSocket框架-Unity太空大戰遊戲-數組

概述0服務器

先看下最終的效果session

服務端多線程

用戶登陸後,認證成功進入遊戲後架構

客戶端

輸入錯誤密碼,有提示信息

主要技術架構

服務端端:

Socket框架【WeaveSocket】

https://gitee.com/dreamsfly900/universal-Data-Communication-System-for-windows/

數據庫【LiteDB】(3.1.4.0)

http://www.litedb.org/

界面UI【WPF】(.Net4.5)

項目源碼圖

Unity3D客戶端:

WeaveSocket官方QQ羣17375149 
  服務端運行圖:

 


主要的用到的類爲:
WeaveTCPcloud類(部分重寫,與原做者源碼不一樣,請注意下)
代碼以下:

using MyTcpCommandLibrary;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Reflection;
using System.Xml;
using WeaveBase;
using WeaveSocketServer;
namespace MyTCPCloud
{
    public class WeaveTCPcloud : IWeaveUniversal
    {
        public event WeaveLogDelegate WeaveLogEvent;

        public event WeaveServerReceiveDelegate WeaveReceiveEvent;

        public event WeaveServerUpdateSocketHander WeaveUpdateEvent;

        public event WeaveServerDeleteSocketHander WeaveDeleteEvent;

        public event WeaveServerUpdateUnityPlayerSetOnLineHander WeaveServerUpdateUnityPlayerSetOnLineEvent;


        //public XmlDocument xml
        //{
        //    get;set;
        //}

        public List<CmdWorkItem> CmdWorkItems
        {
            get
            {
                return _CmdWorkItems;
            }

            set
            {
                _CmdWorkItems = value;
            }
        }

        public WeaveTable weaveTable
        {
            get
            {
                return _weaveTable;
            }

            set
            {
                _weaveTable = value;
            }
        }

        public List<WeaveOnLine> weaveOnline
        {
            get
            {
                return _weaveOnline;
            }

            set
            {
                _weaveOnline = value;
            }
        }

        public List<UnityPlayerOnClient> unityPlayerOnClientList
        {
            get
            {
                return _unityPlayerOnClientList;
            }

            set
            {
                _unityPlayerOnClientList = value;
            }
        }

       // public IWeaveTcpBase P2Server
         public WeaveP2Server P2Server
        {
            get;set;
        }

        public WeaveTcpToken TcpToken
        {
            get
            {
                return _TcpToken;
            }

            set
            {
                _TcpToken = value;
            }
        }

        List<CmdWorkItem> _CmdWorkItems = new List<CmdWorkItem>();
        
        WeaveTable _weaveTable = new WeaveTable();
     
        List<WeaveOnLine> _weaveOnline = new List<WeaveOnLine>();
        
       
       WeaveTcpToken _TcpToken = new WeaveTcpToken();

        //我寫的方法
        List<UnityPlayerOnClient> _unityPlayerOnClientList = new List<UnityPlayerOnClient>();
        
       
        

        public bool Run(WevaeSocketSession myI)
        {
            //ReloadFlies();
            AddMyTcpCommandLibrary();


            weaveTable.Add("onlinetoken", weaveOnline);//初始化一個隊列,記錄在線人員的token
            if (WeaveLogEvent != null)
                WeaveLogEvent("鏈接", "鏈接啓動成功");
            return true;
        }
        /// <summary>
        /// 讀取WeavePortTypeEnum類型後,初始化 new WeaveP2Server("127.0.0.1"),並添加端口;
        /// </summary>
        /// <param name="WeaveServerPort"></param>
        public void StartServer(WeaveServerPort _ServerPort)
        {
           
             // WeaveTcpToken weaveTcpToken = new WeaveTcpToken();
         
               P2Server = new WeaveP2Server("127.0.0.1");

              P2Server.waveReceiveEvent += P2ServerReceiveHander;
               P2Server.weaveUpdateSocketListEvent += P2ServerUpdateSocketHander;
               P2Server.weaveDeleteSocketListEvent += P2ServerDeleteSocketHander;
               //   p2psev.NATthroughevent += tcp_NATthroughevent;//p2p事件,不須要使用
               P2Server.Start( _ServerPort.Port  );//myI.Parameter[4]是端口號

               TcpToken.PortType = _ServerPort.PortType;
               TcpToken.P2Server = P2Server;
              TcpToken.IsToken = _ServerPort.IsToken;
               TcpToken.WPTE = _ServerPort.PortType;
                
               // TcpToken = weaveTcpToken;
            
               // P2Server = p2psev;
            
        }


        public void AddMyTcpCommandLibrary()
        {
            try
            {
                LoginManageCommand loginCmd = new LoginManageCommand();
                loginCmd.ServerLoginOKEvent += UpdatePlayerListSetOnLine;
                AddCmdWorkItems(loginCmd);

                AddCmdWorkItems(new GameScoreCommand());

                AddCmdWorkItems(new ClientDisConnectedCommand());



            }
            catch
            {

            }
        }

        public void AddCmdWorkItems(WeaveTCPCommand cmd)
        {
            cmd.SetGlobalQueueTable(weaveTable, TcpToken);
            CmdWorkItem cmdItem = new CmdWorkItem();
            // Ic.SetGlobalQueueTable(weaveTable, TcpTokenList);
            cmdItem.WeaveTcpCmd = cmd;
            cmdItem.CmdName = cmd.Getcommand();
            GetAttributeInfo(cmd, cmd.GetType(), cmd);
            CmdWorkItems.Add(cmdItem);
        }

       
        public void GetAttributeInfo(WeaveTCPCommand Ic, Type t, object obj)
        {
            foreach (MethodInfo mi in t.GetMethods())
            {
                InstallFunAttribute myattribute = (InstallFunAttribute)Attribute.GetCustomAttribute(mi, typeof(InstallFunAttribute));
                if (myattribute == null)
                {
                }
                else
                {
                    if (myattribute.Dtu)
                    {
                        Delegate del = Delegate.CreateDelegate(typeof(WeaveRequestDataDtuDelegate), obj, mi, true);
                        Ic.Bm.AddListen(mi.Name, del as WeaveRequestDataDtuDelegate, myattribute.Type, true);
                    }
                    else
                    {
                        Delegate del = Delegate.CreateDelegate(typeof(WeaveRequestDataDelegate), obj, mi, true);
                        Ic.Bm.AddListen(mi.Name, del as WeaveRequestDataDelegate, myattribute.Type);
                    }
                }
            }
        }
        void P2ServerDeleteSocketHander(System.Net.Sockets.Socket soc)
        {

            /*我寫的方法*/
            WeaveOnLine hasOnline = weaveOnline.Find(item => item.Socket == soc);

            if (hasOnline != null)
            {
                
                UnityPlayerOnClient uplayer = ConvertWeaveOnlineToUnityPlayerOnClient(hasOnline);

                WeaveDeleteEvent(uplayer);

                weaveOnline.Remove(hasOnline);

                // unityPlayerOnClientList.Remove(uplayer);
                DeleteUnityPlayerOnClient(hasOnline.Socket);
            }
            /**/


            try
            {
                int count = CmdWorkItems.Count;
                CmdWorkItem[] cilist = new CmdWorkItem[count];
                CmdWorkItems.CopyTo(0, cilist, 0, count);
                foreach (CmdWorkItem CI in cilist)
                {
                    try
                    {
                        CI.WeaveTcpCmd.WeaveDeleteSocketEvent(soc);
                    }
                    catch (Exception ex)
                    {
                        if (WeaveLogEvent != null)
                            WeaveLogEvent("EventDeleteConnSoc", ex.Message);
                    }
                }
            }
            catch { }
            try
            {
                int count = weaveOnline.Count;
                WeaveOnLine[] ols = new WeaveOnLine[count];
                weaveOnline.CopyTo(0, ols, 0, count);
                foreach (WeaveOnLine ol in ols)
                {
                    if (ol.Socket.Equals(soc))
                    {
                        foreach (CmdWorkItem CI in CmdWorkItems)
                        {
                            try
                            {
                                WeaveExcCmdNoCheckCmdName(0xff, "out|" + ol.Token, ol.Socket);
                                CI.WeaveTcpCmd.Tokenout(ol);
                            }
                            catch (Exception ex)
                            {
                                if (WeaveLogEvent != null)
                                    WeaveLogEvent("Tokenout", ex.Message);
                            }
                        }
                        weaveOnline.Remove(ol);
                        return;
                    }
                }
            }
            catch { }
        }


        public void UpdatePlayerListSetOnLine(string _userName , System.Net.Sockets.Socket soc)
        {
            foreach(UnityPlayerOnClient oneclient in unityPlayerOnClientList)
            {
                if(oneclient.Socket == soc)
                {
                    oneclient.UserName = _userName;
                    oneclient.isLogin = true;
                    WeaveServerUpdateUnityPlayerSetOnLineEvent(oneclient);
                    break;
                }
            }

           
        }


        void P2ServerUpdateSocketHander(System.Net.Sockets.Socket soc)
        {
           
            #region  讀取 Command接口類,每次有新的Socket加入 從新讀取並設置
            try
            {
                int count = CmdWorkItems.Count;
                CmdWorkItem[] cilist = new CmdWorkItem[count];
                CmdWorkItems.CopyTo(0, cilist, 0, count);
                foreach (CmdWorkItem CI in cilist)
                {
                    try
                    {
                        CI.WeaveTcpCmd.WeaveUpdateSocketEvent(soc);
                    }
                    catch (Exception ex)
                    {
                        if (WeaveLogEvent != null)
                            WeaveLogEvent("EventUpdataConnSoc", ex.Message);
                    }
                }
            }
            catch
            {

            }

            #endregion  發送Token的代碼

            WeaveTcpToken token = TcpToken;
            {
                if (token.IsToken)
                {
                    //生成一個token,後綴帶隨機數
                    string Token = DateTime.Now.ToString("yyyyMMddHHmmssfff") + new Random().Next(1000, 9999);// EncryptDES(clientipe.Address.ToString() + "|" + DateTime.Now.ToString(), "lllssscc");
                    if (token.P2Server.Port == ((System.Net.IPEndPoint)soc.LocalEndPoint).Port)
                    {
                        //向客戶端發送生成的token
                        bool sendok = false;
                        if (token.PortType == WeavePortTypeEnum.Bytes)
                            sendok = token.P2Server.Send(soc, 0xff, token.BytesDataparsing.Get_ByteBystring("token|" + Token + ""));
                        else
                            sendok = token.P2Server.Send(soc, 0xff, "token|" + Token + "");


                        #region  if(sendok)
                        if (sendok)
                        {
                            WeaveOnLine ol = new WeaveOnLine()
                            {
                                Name = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                                Obj = DateTime.Now.ToString("yyyyMMddHHmmssfff")
                            };
                            ol.Token = Token;
                            ol.Socket = soc;
                           
                                WeaveOnLine hasOnline = weaveOnline.Find(item => item.Name == ol.Name);
                                {
                                   if (hasOnline != null)
                                  {
                                    weaveOnline.Remove(hasOnline);

                                    weaveOnline.Add(ol);

                                  }
                                  else
                                  {
                                    weaveOnline.Add(ol);
                                   }
                                }
                               
                           
                            /*我單獨寫的UnityClient*/
                            /*我寫的新方法*/
                            UnityPlayerOnClient hasPlayerIn = unityPlayerOnClientList.Find(item => item.Name == ol.Name);
                                if (hasPlayerIn != null)
                                {
                                    WeaveDeleteEvent(hasPlayerIn);
                                    unityPlayerOnClientList.Remove(hasPlayerIn);

                                }
                                /*我寫的方法結束*/

                                UnityPlayerOnClient uplayer = ConvertWeaveOnlineToUnityPlayerOnClient(ol);
                                // unityPlayerOnClientList.Add(uplayer);
                                AddUnityPlayerClient_CheckSameItem(uplayer , ol.Name);
                                WeaveUpdateEvent(uplayer);
                            
                            

                            /**/


                            foreach (CmdWorkItem cmdItem in CmdWorkItems)
                            {
                                try
                                {
                                    WeaveExcCmdNoCheckCmdName(0xff, "in|" + ol.Token, ol.Socket);
                                    cmdItem.WeaveTcpCmd.TokenIn(ol);
                                }
                                catch (Exception ex)
                                {
                                    if (WeaveLogEvent != null)
                                        WeaveLogEvent("Tokenin", ex.Message);
                                }
                            }
                            return;
                        }
                        #endregion
                    }
                }
                else
                {
                    WeaveOnLine ol = new WeaveOnLine()
                    {
                        Name = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                        Obj = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                        Socket = soc,
                        Token = DateTime.Now.ToString("yyyyMMddHHmmssfff")

                    };
                    weaveOnline.Add(ol);


                    /*我單獨寫的UnityClient*/
                    UnityPlayerOnClient hasPlayerIn = unityPlayerOnClientList.Find(item => item.Socket == soc);
                    if (hasPlayerIn != null)
                    {
                        WeaveDeleteEvent(hasPlayerIn);
                        unityPlayerOnClientList.Remove(hasPlayerIn);

                    }

                    UnityPlayerOnClient uplayer = ConvertWeaveOnlineToUnityPlayerOnClient(ol);
                    AddUnityPlayerClient_CheckSameItem(uplayer, ol.Name);
                    WeaveUpdateEvent(uplayer);
                    /**/
                    //  ol.Token = DateTime.Now.ToString();
                    //  ol.Socket = soc;


                }

            }
        }
        void P2ServerReceiveHander(byte command, string data, System.Net.Sockets.Socket soc)
        {
            if(command == (byte)CommandEnum.ClientSendDisConnected)
            {
                P2Server.CliendSendDisConnectedEvent(soc);

                /*我寫的方法*/
                WeaveOnLine hasOnline = weaveOnline.Find(item => item.Socket == soc);

                if (hasOnline != null)
                {

                    UnityPlayerOnClient uplayer = ConvertWeaveOnlineToUnityPlayerOnClient(hasOnline);

                    WeaveDeleteEvent(uplayer);

                    weaveOnline.Remove(hasOnline);

                    // unityPlayerOnClientList.Remove(uplayer);
                    DeleteUnityPlayerOnClient(hasOnline.Socket);
                }

              
                /**/
                return;
            }

            try
            {
                //觸發接收到信息的事件...
                /*我寫的方法*/
                WeaveOnLine hasOnline = weaveOnline.Find(item => item.Socket == soc);
               
                if(hasOnline != null)
                {
                    UnityPlayerOnClient uplayer = ConvertWeaveOnlineToUnityPlayerOnClient(hasOnline);

                    WeaveReceiveEvent(command, data, uplayer);

                }
                /**/

                if (command == 0xff)
                {
                    //若是是網關command 發過來的 命名,那麼執行下面的
                    WeaveExcCmdNoCheckCmdName(command, data, soc);
                   
                    try
                    {
                        string[] temp = data.Split('|');
                        if (temp[0] == "in")
                        {
                            //加入onlinetoken
                            WeaveOnLine ol = new WeaveOnLine();
                            ol.Token = temp[1];
                            ol.Socket = soc;
                            weaveOnline.Add(ol);
                            foreach (CmdWorkItem CI in CmdWorkItems)
                            {
                                try
                                {
                                    CI.WeaveTcpCmd.TokenIn(ol);
                                }
                                catch (Exception ex)
                                {
                                    WeaveLogEvent?.Invoke("Tokenin", ex.Message);
                                }
                            }
                            return;
                        }
                        else if (temp[0] == "Restart")
                        {
                            int count = weaveOnline.Count;
                            WeaveOnLine[] ols = new WeaveOnLine[count];
                            weaveOnline.CopyTo(0, ols, 0, count);
                            string IPport = ((System.Net.IPEndPoint)soc.RemoteEndPoint).Address.ToString() + ":" + temp[1];
                            foreach (WeaveOnLine ol in ols)
                            {
                                try
                                {
                                    if (ol.Socket != null)
                                    {
                                        String IP = ((System.Net.IPEndPoint)ol.Socket.RemoteEndPoint).Address.ToString() + ":" + ((System.Net.IPEndPoint)ol.Socket.RemoteEndPoint).Port;
                                        if (IP == IPport)
                                        {
                                            ol.Socket = soc;
                                        }
                                    }
                                }
                                catch { }
                            }
                        }
                        else if (temp[0] == "out")
                        {
                            ////移出onlinetoken
                            int count = weaveOnline.Count;
                            WeaveOnLine[] ols = new WeaveOnLine[count];
                            weaveOnline.CopyTo(0, ols, 0, count);
                            foreach (WeaveOnLine onlinesession in ols)
                            {
                                if (onlinesession.Token == temp[1])
                                {
                                    foreach (CmdWorkItem cmdItem in CmdWorkItems)
                                    {
                                        try
                                        {
                                            cmdItem.WeaveTcpCmd.Tokenout(onlinesession);
                                        }
                                        catch (Exception ex)
                                        {
                                            WeaveLogEvent?.Invoke("Tokenout", ex.Message);
                                        }
                                    }
                                    weaveOnline.Remove(onlinesession);
                                    return;
                                }
                            }
                        }
                    }
                    catch { }
                    return;
                }

                else
                    WeaveExcCmd(command, data, soc);
            }
            catch
            {
                return;
            }
            //System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(exec));
        }



      


        /// <summary>
        /// 網關0xff這個command發來的...命令
        /// </summary>
        /// <param name="command"></param>
        /// <param name="data"></param>
        /// <param name="soc"></param>
        public void WeaveExcCmdNoCheckCmdName(byte command, string data, System.Net.Sockets.Socket soc)
        {
            foreach (CmdWorkItem cmd in CmdWorkItems)
            {
                try
                {
                    cmd.WeaveTcpCmd.Runcommand(command, data, soc);
                }
                catch (Exception ex)
                {
                    WeaveLogEvent?.Invoke("receiveevent", ex.Message);
                }
            }
        }


        /// <summary>
        /// 不是0xff這個command發來的...命令
        /// </summary>
        /// <param name="command"></param>
        /// <param name="data"></param>
        /// <param name="soc"></param>
        public void WeaveExcCmd(byte command, string data, System.Net.Sockets.Socket soc)
        {
            foreach (CmdWorkItem cmd in CmdWorkItems)
            {
                if (cmd.CmdName == command)
                {
                    try
                    {
                        cmd.WeaveTcpCmd.Run(data, soc);
                        cmd.WeaveTcpCmd.RunBase(data, soc);
                    }
                    catch (Exception ex)
                    {
                        WeaveLogEvent?.Invoke("receiveevent", ex.Message);
                    }
                }
            }
        }

        public UnityPlayerOnClient ConvertWeaveOnlineToUnityPlayerOnClient(WeaveOnLine  wonline)
        {
            UnityPlayerOnClient uplayer = new UnityPlayerOnClient()
            {
                Obj = wonline.Obj,
                Socket = wonline.Socket,
                Token = wonline.Token,
                Name = wonline.Name
            };



            return uplayer;

        }

        public void DeleteUnityPlayerOnClient(Socket osc)
        {
            try
            {
                if (unityPlayerOnClientList.Count > 0)
                    unityPlayerOnClientList.Remove(unityPlayerOnClientList.Find(u => u.Socket == osc));
            }
            catch
            {

            }
        }



        public void AddUnityPlayerClient_CheckSameItem(UnityPlayerOnClient item ,string itemName)
        {
            System.Threading.Thread.Sleep(500);
            lock (this)
            {
                if (unityPlayerOnClientList.Find(i => i.Name == itemName) != null)
                    return;

                else
                    unityPlayerOnClientList.Add(item);
            }
        }
        //public class CmdWorkItem
        //{
        //    public byte CmdName
        //    {
        //        get;set;
        //    }
        //    public WeaveTCPCommand WeaveTcpCmd
        //    {
        //        get;set;
        //    }
        //}
    }
}

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

重點說下AddMyTcpCommandLibrary方法
加載幾個繼承自 WeaveTCPCommand的類,裏面寫有一些方法,當服務器接收到客戶端的一些參數後,能夠直接跳轉執行裏面的寫的方法,你能夠新建一個類庫項目(我這裏命名爲MyTcpCommandLibrary),而後引用項目 WeaveBase和WeaveSocketServer。在MyTcpCommandLibrary項目下新建幾個類(根據你想要的邏輯),類繼承WeaveTCPCommand,而後有具體的方法單獨寫出來,如

[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  
                ServerLoginOKEvent(get_client_Send_loginModel.userName, soc);


            }
            SendRoot<bool>(soc, (byte)CommandEnum.ServerSendLoginResult, "ServerBackLoginResult", loginOk , 0, wsession.Token);
            //發送人數給客戶端
            //參數1,發送給客戶端對象,參數2,發送給客戶端對應的方法,參數3,人數的實例,參數4,此處無做用,參數5,客戶端這次token
        }

當客戶端發送命名爲 Getcommand() 返回的命令byte,而且參數含方法名,便可直接調用服務端WeaveTCPCommand寫的這個CheckLogin方法
客戶端調用示例

weaveSocketGameClient.SendRoot<LoginTempModel>((byte)CommandEnum.ClientSendLoginModel, "CheckLogin", user, 0);

再說下前端WPF啓動服務器開始監聽的代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using WeaveBase;
using System.Net.Sockets;
using MyTCPCloud;
using System.Windows.Threading;

namespace WeavingSocketServerWPF
{
    /// <summary>
    /// MyUnityServer.xaml 的交互邏輯
    /// </summary>
    public partial class MyUnityServer : Window
    {
        public MyUnityServer()
        {
            InitializeComponent();

           // DispatcherFunction();
        }
        /// <summary>
        /// 監聽端口列表,,能夠選擇監聽多個端口
        /// </summary>
        WeaveServerPort wserverport = new WeaveServerPort();
        WeaveTCPcloud weaveTCPcloud = new WeaveTCPcloud();

        List<MyListBoxItem> loginedUserList = new List<MyListBoxItem>();

        List<MyListBoxItem> connectedSocketItemList = new List<MyListBoxItem>();
        // DispatcherTimer dispatcherTimer = new DispatcherTimer();

        private void StartListen_button_Click(object sender, RoutedEventArgs e)
        {
            //設置登錄後的用戶列表Listbox的數據源
            LoginedUser_listBox.ItemsSource = loginedUserList;
            //設置鏈接到服務器的Socket列表的Listbox的數據源
            ConnectedSocket_listBox.ItemsSource = connectedSocketItemList;

            WevaeSocketSession mif = new WevaeSocketSession();
           
            weaveTCPcloud.Run(mif);


            wserverport.IsToken = true;
            wserverport.Port = Convert.ToInt32(Port_textBox.Text);
            wserverport.PortType = WeavePortTypeEnum.Json;
         
            weaveTCPcloud.StartServer(wserverport);


            weaveTCPcloud.WeaveReceiveEvent += OnWeaveReceiveMessage;

            weaveTCPcloud.WeaveDeleteEvent += OnWeaveDeleteSocket;

            weaveTCPcloud.WeaveUpdateEvent += OnWeaveUpdateSocket;

            weaveTCPcloud.WeaveServerUpdateUnityPlayerSetOnLineEvent += OnWeaveServerUpdateUnityPlayerSetOnLineEvent;

            StartListen_button.Content = "正在監聽";

            StartListen_button.IsEnabled = false;
            
        }

        private void OnWeaveServerUpdateUnityPlayerSetOnLineEvent(UnityPlayerOnClient gamer)
        {

            
            //throw new NotImplementedException();
            //當有用戶 帳號密碼登錄成功的時候
            AddListBoxItemAction(loginedUserList, CopyUnityPlayerOnClient(gamer));
            SetServerReceiveText("--觸發了一次(OnWeaveServerUpdateUnityPlayerSetOnLineEvent)" + Environment.NewLine);

        }

        private void OnWeaveUpdateSocket(UnityPlayerOnClient gamer)
        {
            SetServerReceiveText("--觸發了一次(OnWeaveUpdateSocket)" + Environment.NewLine);

            //有 Sokcet客戶端鏈接到服務器的時候,暫未 帳號,密碼認證狀態

            AddListBoxItemAction(connectedSocketItemList, CopyUnityPlayerOnClient(gamer) );
           
        }

       

        private void OnWeaveDeleteSocket(UnityPlayerOnClient gamer)
        {
            SetServerReceiveText("--退出事件,,觸發了一次(OnWeaveDeleteSocket)" + Environment.NewLine);

            RemoveListBoxItemAction(connectedSocketItemList, CopyUnityPlayerOnClient(gamer));

            RemoveListBoxItemAction(loginedUserList, CopyUnityPlayerOnClient(gamer));


        }

        private void OnWeaveReceiveMessage(byte command, string data, UnityPlayerOnClient  gamer)
        {
           

            WeaveSession ws = Newtonsoft.Json.JsonConvert.DeserializeObject<WeaveSession>(data);

            SetServerReceiveText("接收到新信息:  "  + ws.Root  + Environment.NewLine );

         
        }

        private void StopListen_button_Click(object sender, RoutedEventArgs e)
        {

            weaveTCPcloud.P2Server = null;

            weaveTCPcloud = null;

            Application.Current.Shutdown();
            Environment.Exit(0);// 能夠當即中斷程序執行並退出
        }

        private void SendMsg_button_Click(object sender, RoutedEventArgs e)
        {
           
            string serverMsg = InputSendMessage_textBox.Text;
            int unityGamecount = weaveTCPcloud.unityPlayerOnClientList.Count;
            if (string.IsNullOrEmpty(serverMsg) || weaveTCPcloud.weaveOnline.Count==0)
                return;

            WeaveOnLine[] _allWeaveOnLine = new WeaveOnLine[weaveTCPcloud.weaveOnline.Count];

            weaveTCPcloud.weaveOnline.CopyTo(_allWeaveOnLine);

            foreach (WeaveOnLine oneWeaveOnLine in _allWeaveOnLine)
            {
                weaveTCPcloud.P2Server.Send(oneWeaveOnLine.Socket, 0x01, "服務器主動給全部客戶端發消息了: " + serverMsg);
            }

           // MessageBox.Show("客戶端在線數量:"+ _allWeaveOnLine.Length);
        }


        private void UpdateServerReceiveTb(TextBlock tb, string text)
        {
            tb.Text += text;
        }

        private void SetServerReceiveText(string newtext)
        {
            Action<TextBlock, String> updateAction = new Action<TextBlock, string>(UpdateServerReceiveTb);
            ServerReceive_textBlock.Dispatcher.BeginInvoke(updateAction, ServerReceive_textBlock, newtext);

        }

        public MyListBoxItem CopyUnityPlayerOnClient(UnityPlayerOnClient one)
        {
            MyListBoxItem item = new MyListBoxItem()
            {
                UIName_Id = one.Socket.RemoteEndPoint.ToString(),
                ShowMsg = "UserIP:" + one.Socket.RemoteEndPoint.ToString() + " -Token:" + one.Token,
                UserName = one.UserName,
                Ip = one.Socket.RemoteEndPoint.ToString()
            };
            return item;
        }

        public void AddListBoxItem(List<MyListBoxItem> sList  , MyListBoxItem one)
        {
          

            sList.Add(one);
            CheckListBoxSource();
        }

        public void AddListBoxItemAction(List<MyListBoxItem> sList, MyListBoxItem one)
        {
            Action< List < MyListBoxItem >  , MyListBoxItem>  addListBoxItemAction =
            
                new Action<List<MyListBoxItem>  , MyListBoxItem>(AddListBoxItem);

            this.Dispatcher.BeginInvoke(addListBoxItemAction,sList , one);
        }


        public void RemoveListBoxItem(List<MyListBoxItem> sList, MyListBoxItem one)
        {
            MyListBoxItem item = sList.Find(i=>i.Ip == one.Ip);

            if(item != null)
            {
                sList.Remove(item);
            }


            CheckListBoxSource();
        }

        public void RemoveListBoxItemAction(List<MyListBoxItem> sList, MyListBoxItem one)
        {
            Action<List<MyListBoxItem>, MyListBoxItem> removeListBoxItemAction =

                new Action<List<MyListBoxItem>, MyListBoxItem>(RemoveListBoxItem);

            this.Dispatcher.BeginInvoke(removeListBoxItemAction, sList , one);
        }

        public void CheckListBoxSource()
        {
            //數據發生變化後,從新設置登錄後的用戶列表Listbox的數據源
            LoginedUser_listBox.ItemsSource = null;
            LoginedUser_listBox.ItemsSource = loginedUserList;
            //數據發生變化後,從新設置鏈接到服務器的Socket列表的Listbox的數據源
            ConnectedSocket_listBox.ItemsSource = null;
           ConnectedSocket_listBox.ItemsSource = connectedSocketItemList;
        }

        protected override void OnClosed(EventArgs e)
        {
            weaveTCPcloud.P2Server = null;

            weaveTCPcloud = null;

            //Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
            //if (this.IsAfreshLogin == true) return;
            Application.Current.Shutdown();
            Environment.Exit(0);// 能夠當即中斷程序執行並退出
            base.OnClosed(e);
        }


    }

    public class MyListBoxItem
    {
        public string UIName_Id { get; set; }

        public string Ip { get; set; }
        public string ShowMsg { get; set; }

        public string UserName { get; set; }
    }
}

主要的啓動服務器的代碼爲

WeaveServerPort wserverport = new WeaveServerPort();
        WeaveTCPcloud weaveTCPcloud = new WeaveTCPcloud();

            WevaeSocketSession mif = new WevaeSocketSession();
            //不知道這裏幹嗎,沒搞懂
            weaveTCPcloud.Run(mif);


            wserverport.IsToken = true;
            wserverport.Port = Convert.ToInt32(Port_textBox.Text);
            wserverport.PortType = WeavePortTypeEnum.Json;
         
            weaveTCPcloud.StartServer(wserverport);


            weaveTCPcloud.WeaveReceiveEvent += OnWeaveReceiveMessage;

            weaveTCPcloud.WeaveDeleteEvent += OnWeaveDeleteSocket;

            weaveTCPcloud.WeaveUpdateEvent += OnWeaveUpdateSocket;

            weaveTCPcloud.WeaveServerUpdateUnityPlayerSetOnLineEvent += OnWeaveServerUpdateUnityPlayerSetOnLineEvent;

事件分別是
weaveTCPcloud.WeaveReceiveEvent += OnWeaveReceiveMessage;
接受到客戶端發來的數據事件(這裏若是發來的數據第一位byte命令跟上面的MyTcpCommandLibrary項目裏面,繼承自WeaveTCPCommand類,具體的返回的Getcommand()方法返回的byte命名相同,則會進入那個類進行處理)
假如客戶端發送代碼以下
weaveSocketGameClient.SendRoot<LoginTempModel>( 0x02 , "CheckLogin", user, 0);
表示客戶端發送的命名是0x02 ,數據實體類是 LoginTempModel (數據發送報文格式,咱們稍後再說)
服務端 MyTcpCommandLibrary有個類有以下代碼

public class LoginManageCommand  : WeaveTCPCommand
    {
        public delegate void ServerLoginOK(string _u,Socket _s);

        public event ServerLoginOK ServerLoginOKEvent;

        public override byte Getcommand()
        {

            //此CLASS的實例,表明的指令,指令從0-254,0x9c與0xff爲內部指令不能使用。
            //0x01的意思是,只要是0x01的指令,都會進入本實例進行處理
            //return 0x01;
            return (byte)CommandEnum.ClientSendLoginModel; //0x02;
        }

        public override bool Run(string data, Socket soc)
        {
           
            //此事件是接收事件,data 是String類型的數據,soc是發送人。
            return true;
        }

        public override void WeaveBaseErrorMessageEvent(Socket soc, WeaveSession _0x01, string message)
        {
            //錯誤異常事件,message爲錯誤信息,soc爲產生異常的鏈接
        }

        public override void WeaveDeleteSocketEvent(Socket soc)
        {
            //此事件是當有人中斷了鏈接,此事件會被調用
        }

        public override void WeaveUpdateSocketEvent(Socket soc)
        {
            //此事件是當有人新加入了鏈接,此事件會被調用
        }

        [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  
                ServerLoginOKEvent(get_client_Send_loginModel.userName, soc);


            }
            SendRoot<bool>(soc, (byte)CommandEnum.ServerSendLoginResult, "ServerBackLoginResult", loginOk , 0, wsession.Token);
            //發送人數給客戶端
            //參數1,發送給客戶端對象,參數2,發送給客戶端對應的方法,參數3,人數的實例,參數4,此處無做用,參數5,客戶端這次token
        }


        private void AddSystemData()
        {
            GameDataAccess.BLL.UserTableBLL myBLL = new GameDataAccess.BLL.UserTableBLL();

            if(  myBLL.CheckDataBaseIsNull())
            {
                myBLL.AddTestData();
            }
        }

        private bool CheckUserCanLoginIn(LoginTempModel m)
        {
            GameDataAccess.BLL.UserTableBLL myBLL = new GameDataAccess.BLL.UserTableBLL();
            return myBLL.CheckUserNamePassword(m.userName, m.password);
        }



    }

那麼則會調用服務端的CheckLogin方法
weaveTCPcloud.WeaveDeleteEvent += OnWeaveDeleteSocket;
當有Socket鏈接斷開的事件
            

weaveTCPcloud.WeaveUpdateEvent += OnWeaveUpdateSocket;
當有新的Socket鏈接-首次鏈接成功的事件
            weaveTCPcloud.WeaveServerUpdateUnityPlayerSetOnLineEvent += OnWeaveServerUpdateUnityPlayerSetOnLineEvent;
這是我根據源碼修改的一個事件,當客戶端鏈接成功,而且發送帳號密碼到服務器,服務器查找數據庫後,確認給客戶端能夠登錄遊戲後,把當前用戶設置爲已經上線的遊戲玩家的事件
 

數據格式以下圖

發送數據的主要代碼爲

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; //表示第一位byte的命令
  b[1] = (byte)part3_length.Length; //表示第三部分數據的長度
  part3_length.CopyTo(b, 2);
  //擴充 第四部分數據(待發送的數據)的長度,擴充到b數組第三位開始的後面
  sendb.CopyTo(b, 2 + part3_length.Length);
  //擴充 第四部分數據實際的數據,擴充到b數組第三部分結尾後面...
  socket.Send( b );

客戶端代碼結構

 

 

登錄界面

 

 

遊戲場景

 

 

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

主要的邏輯流程

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

啓動程序

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

玩家輸入帳號密碼

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

點擊登錄按鈕

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

鏈接服務器(若是成功),繼續發送帳號密碼到服務器的命令

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

服務器接收帳號密碼,進行查找數據庫操做

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

發送查找結果給客戶端......

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

若是客戶端接收到服務器發過來的登錄成功消息(跳轉到遊戲場景),

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

若是返回失敗,那麼提示帳號密碼錯誤

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

客戶端再次發送查找當前用戶的歷史積分數據的命令

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

(正在遊戲場景運行中)

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

客戶端接受到歷史積分數據,並更新顯示到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);
                }
            }
        }

    }
}

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遊戲邏輯代碼在這裏再也不細說

相關文章
相關標籤/搜索