Unity太空大战游戏-Socket网络通信教学示例


声明:本文转载自https://my.oschina.net/u/2476624/blog/1579244,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

项目下载地址

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

 Example /Unity3D_2DShootServer_Client 项目文件位置。

教程编写有 SuperLinMeng 提供,QQ:2360450496

WeaveSocket通讯框架官方QQ群17375149

WeaveSocket框架-Unity太空大战游戏-

概述0

先看下最终的效果

服务端

用户登录后,认证成功进入游戏后

客户端

输入错误密码,有提示信息

主要技术架构

服务端端:

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游戏逻辑代码在这里不再细说

 

 

 

 

 

 

 

本文发表于2017年11月24日 12:23
(c)注:本文转载自https://my.oschina.net/u/2476624/blog/1579244,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2760 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1