您的位置:首页 > 其它

游戏制作-联网对战丛林战争制作笔记(一)

2017-12-09 14:27 337 查看
          开篇先说明,这个游戏制作也是我跟随别人的教程制作的游戏,因此想要了解更多的内容可以去看siki老师的视频,我这里做笔记的目的有两个,一个是帮助喜欢看文字版教程的朋友进一步的学习,一个是保存自己在学习中的一个逻辑和思路,如果看到这个视频会对你有帮助,那就再好不过了,当然这里的话是其中百分之30的内容,后面的制作我会放在我的其他博客下继续

 

1.    关于IP和端口号的知识

我们经常申请的端口号是49152-65535,1024以前的基本是知名端口

2.    绑定我们的IP和端口号

namespace tcp服务器端
{
   classProgram
    {
        staticvoid Main(string[] args)
        {
            //首先,创建我们的Socket,是ipv4的地址,以流的形式传输,使用的是tcp协议
            Socketmysocket =
newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //第二部,创建我们的ip地址
           IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
            //将ip地址和我们指定的端口号进行绑定
           IPEndPoint ipendpoint =
new IPEndPoint(ipaddress, 88);
            //将socket和端口号进行绑定
           mysocket.Bind(ipendpoint);
        }
    }
}

3.  创建我们的服务器端

这里的话,我们让socket开始监听以后,就创建一个接受客户端连接的socket,我们一般是用receive和send来收发数据,这里要注意传递的数据都是字节数组,我们要将它转变成

   classProgram
   {
       staticvoid Main(string[] args)
       {
            //首先,创建我们的Socket,是ipv4的地址,以流的形式传输,使用的是tcp协议
            Socket mysocket =
new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
            //第二部,创建我们的ip地址
            IPAddress ipaddress =IPAddress.Parse("127.0.0.1");
            //将ip地址和我们指定的端口号进行绑定
            IPEndPoint ipendpoint =
new IPEndPoint(ipaddress,88);
            //将socket和端口号进行绑定
            mysocket.Bind(ipendpoint);
            mysocket.Listen(0);
            Socket clientSocket =mysocket.Accept();//接受客户端连接
 
            //向客户端发送一条信息
            string msg =
"hello客户端";
            byte[] data = System.Text.Encoding.UTF8.GetBytes(msg);
            clientSocket.Send(data);
            //从客户端接受数据
            byte[] getdata =
newbyte[1024];
            int count = clientSocket.Receive(getdata);
            //这里表示用getdata这个数组来接受客户端传递的数据,再将传递数据长度的字节数组转换成字符串再输出
            string msg2 = System.Text.Encoding.UTF8.GetString(getdata, 0,count);
            Console.WriteLine(msg2);
            clientSocket.Close();
            mysocket.Close();
 
 
 
 
 
        }

4.    创建我们的客户端

客户端也是一样创建自己的socket,和服务器提供的端口相连接,然后再收发信息即可

5.  using System;
6.  using System.Collections.Generic;
7.  using System.Linq;
8.  using System.Text;
9.  using System.Threading.Tasks;
10.using System.Net.Sockets;
11.using System.Net;
12. 
13.namespace tcp客户端
14.{
15.    classProgram
16.    {
17.        staticvoid Main(string[]
args)
18.        {
19.            Socket clientSocket =
newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
20.            IPEndPoint iPEndPoint =
newIPEndPoint(IPAddress.Parse("10.128.230.79"), 88);
21.            clientSocket.Connect(iPEndPoint);
22.            //客户端接受输出
23.            byte[] receivedata =
newbyte[1024];
24.            int count = clientSocket.Receive(receivedata);
25.            string message = Encoding.UTF8.GetString(receivedata, 0,count);
26.            Console.WriteLine(message);
27.            
28.            //客户端向服务器发送数据
29.            string msg2 = Console.ReadLine();
30.            clientSocket.Send(Encoding.UTF8.GetBytes(msg2));
31.            
32.            Console.ReadKey();
33.            clientSocket.Close();
34. 
35. 
36.        }
37.    }
38. 
}

5.如何异步获取到数据

  这里我们使用一个BeginReceive开始异步接受数据,传递过来我们的客户端这个参数,然后重复调用一个AsyncCallBack的方法,通过begin和end来实现多次对于信息的接受

  staticbyte[] databuffer =
newbyte[1024];

       clientSocket.BeginReceive(databuffer, 0, 1024, SocketFlags.None,AsyncCallback, clientSocket);
       }
       staticvoidAsyncCallback(IAsyncResult ar){
 
            Socket clientSocket = ar.AsyncStateas Socket;
            int count = clientSocket.EndReceive(ar);
            string msg = Encoding.UTF8.GetString(databuffer, 0, count);
            Console.WriteLine("从客户端接受信息" + msg);
           clientSocket.BeginReceive(databuffer, 0, 1024, SocketFlags.None,AsyncCallback, clientSocket);
 
 
 
        }

当然客户端的话,只要while True发送信息即可

    //客户端向服务器发送数据
            while (true)
            {
                string msg2 = Console.ReadLine();
               clientSocket.Send(Encoding.UTF8.GetBytes(msg2));
            }

6.异步与客户端建立连接

想要同时和多个客户端进行连接,也是使用一个mySocket.BeginAccept和endAccept来进行开始接受连接和结束连接,多次执行即可实现和多个客户端建立连接

   staticvoid StartSocket()
       {
           //首先,创建我们的Socket,是ipv4的地址,以流的形式传输,使用的是tcp协议
            Socket mysocket =
newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //第二部,创建我们的ip地址
            IPAddress ipaddress =IPAddress.Parse("10.128.230.79");
            //将ip地址和我们指定的端口号进行绑定
            IPEndPoint ipendpoint =
newIPEndPoint(ipaddress, 88);
            //将socket和端口号进行绑定
            mysocket.Bind(ipendpoint);
            mysocket.Listen(0);
           mysocket.BeginAccept(AcceptCallback, mysocket);//异步接受多个客户端的连接
           
         
       }
       staticvoidAcceptCallback(IAsyncResult ar)
       {
         
            Socket mysocket = ar.AsyncState
as Socket;
            //这里表示完成一次客户端的连接
            Socket clientSocket=mysocket.EndAccept(ar);
            //向客户端发送一条信息
            string msg =
"hello客户端";
            byte[] data = System.Text.Encoding.UTF8.GetBytes(msg);
            clientSocket.Send(data);
           
           
           //我们异步从客户端那里接受多条数据
           clientSocket.BeginReceive(databuffer, 0, 1024, SocketFlags.None,AsyncCallback, clientSocket);
            //这里就是继续等待下一个客户端的连接
           mysocket.BeginAccept(AcceptCallback, mysocket);
 
 
 
        }

7.处理客户端关闭的异常

这里我们使用try catch捕捉异常就可以处理客户端远程强制退出的问题,当我们正常关闭的时候,客户端会向服务器发送长度为0的数据,所以我们这里判断一下如果为0,就关闭与客户端的连接

try
            {
               clientSocket = ar.AsyncState
as Socket;
                int count = clientSocket.EndReceive(ar);
                if (count == 0)
                {
                    clientSocket.Close();
                }
            string msg = Encoding.UTF8.GetString(databuffer, 0, count);
            Console.WriteLine("从客户端接受信息" + msg);
           clientSocket.BeginReceive(databuffer, 0, 1024, SocketFlags.None,AsyncCallback, clientSocket);
             }
            catch(Exception e)
            {
                Console.WriteLine(e);
                if (clientSocket !=
null)
               {
                    clientSocket.Close();
                }
            }

这里我们也可以让客户端正常关闭

当输出c,就断开连接

while (true)
            {
                string msg2 = Console.ReadLine();
               clientSocket.Send(Encoding.UTF8.GetBytes(msg2));
               if (msg2 ==
"c")
                {
                    clientSocket.Close();
                    return;
                }
            }

8.tcp中的粘包和分包

这个粘包和分包是tcp的优化性能

粘包是如果信息过短就会将多次信息打一个包发送,如果信息过长则会分成多个包进行发送

在游戏开发中,我们常会产生多次小信息的传输,这里来讲解解决方案

我们可以在数值传输前加一个数据长度作为判断,假设你定义为40个字节,如果长度小于40个字节,就继续接受,如果到达40个字节,就进行传输

这里当我们要传递一个值类型的数据,就可以用BitConverter.GetBytes这种方式,将它转变一个四个字节的字节数组,这样就可以避免粘包的问题

下面就是一个解决的例子,我们用这个方法对字符串进行转换即可,我们把它做成一个工具类可以随时进行调用

//在这里专门创建一个方法,用来计算传递的字符串的长度,并且将它组拼成一个新的数组用来避免粘包的产生
       publicstaticbyte[] GetBytes(string
data)
       {
            //将字符串转变为数组
            byte[] databuf = Encoding.UTF8.GetBytes(data);
            //计算字节数组长度
            int datalength = databuf.Length;
            //将它转变为4个字节长度的字节数组用来计算长度
            byte[]countLength= BitConverter.GetBytes(datalength);
            //组拼成新的字节数组,即长度加原本的数组
            byte[] newByte = countLength.Concat(databuf).ToArray();
            return newByte;
        }

9.关于服务器如何去接受客户端分包的信息

首先,我们让客户端向服务器循环发送100条输出,这种数据如果不进行解析就会出现粘包的情况

for (int i = 0; i < 100;i++)
            {
                //循环向客户端输出100条数据
               clientSocket.Send(Message.GetBytes(i.ToString()));
            }

然后,我们创建一个Message类来处理各种客户端传递过来的信息,首先,定义一个数组来接受客户端的信息,然后一个startIndex来记录当前传递过来的数据在数组中的位置,RemainLength记录剩余还能使用的长度,addCount用来更新当前数组存放到什么位置

  这里讲解一下我们的解析方法,当更新完StartIndex后,我们就要判断它的长度,首先用BitConvert.toInt32来获取数组的长度,如果超过了开始我们定义的数据长度的话,那就是我们现在解析完全的数据,我们用Encoding.Utf8来将字节数组进行转换,然后用Array.copy()来更新我们的数组,也就是将解析完全的数据移除数组,然后再更新我们的StartIndex

classMessage
   {   
       //每条信息存储的数组
       byte[] data=
newbyte[1024];
       //这个是记录当前数组存储到第几个字节的标志位
       intstartIndex = 0;
       publicbyte[] Data
       {
            get {
return data; }
       }
       publicint StartIndex
       {
            get {
return startIndex; }
       }
       publicint RemainLength
       {
            get {
return data.Length - startIndex; }
       }
       publicvoid AddCount(int count)
       {
            startIndex += count;
       }
       publicvoid ReadMessage()
       {
 
            while (true)
            {
                if (startIndex <= 4)
                {
                    return;
                }
                //读取数组的长度,自动省略前四个字节长度
                int count = BitConverter.ToInt32(data, 0);
                if (startIndex - 4 >= count)
                {
                    String s =Encoding.UTF8.GetString(data, 4, count);
                    Console.WriteLine("解析了一条数据:" + s);
                    Array.Copy(data, count + 4,data, 0, startIndex - count - 4);
                    startIndex -= (count + 4);
                }
                else {
break; }
 
            }
       }
}

然后,我们在服务器中调用这个Message来的方法,首先我们接收到客户端的信息,存放到定义的数组里面,从开始索引开始存储,然后可存储的长度和数组剩余长度有关,如果超出的话就不会再进行接受

每次当我们接受到数据的时候,我们就获取数据长度,然后更新StartIndex,然后调用Message的解析方法,这样就可以循环解析数据并且避免了粘包的问题

lientSocket.BeginReceive(msg3.Data,msg3.StartIndex, msg3.RemainLength, SocketFlags.None, AsyncCallback,clientSocket);
            //这里就是继续等待下一个客户端的连接
           mysocket.BeginAccept(AcceptCallback, mysocket);
 
 
 
       }
       staticvoidAsyncCallback(IAsyncResult ar) {
 
            Socket clientSocket =
null;
            try
           {
               clientSocket = ar.AsyncState
as Socket;
                int count = clientSocket.EndReceive(ar);
                //解析接收到的数据
              
                msg3.AddCount(count);
                msg3.ReadMessage();
                if (count == 0)
                {
                    clientSocket.Close();
                }
          
               clientSocket.BeginReceive(msg3.Data, msg3.StartIndex, msg3.RemainLength,SocketFlags.None, AsyncCallback, clientSocket);
10.使用mysql做查询操作
   因为我们的丛林战争要使用mysql做数据库,这里来讲解一下mysql用法,首先我们要用msql创建一个数据库,定义好它的名字,连接ip地址,端口号,连接的用户名和密码,接着就是打开连接,创建命令语句,执行命令,然后按照列名读取出数据,具体操作可以参照代码和注释啦
                classProgram
   {
       staticvoid Main(string[] args)
       {
            string con =
"Database=test_007;DataSource=localhost;port=3306;User Id=root;Password=1234;";
            //创建数据库的连接
            MySqlConnection coon =
newMySqlConnection(con);
            //开启和数据库的连接
            coon.Open();
            //书写数据库操作的命令和指定的连接
            MySqlCommand command =
new MySqlCommand("select * from user",coon);
            //执行查询操作并且将信息传递给reader
            MySqlDataReader reader =command.ExecuteReader();
            //这个方法会查询一行数据然后判断下一行是否还有数据
            while (reader.Read())
           {
                //根据列名获得数据
                string username = reader.GetString("username");
                string password = reader.GetString("password");
                Console.WriteLine(username +
":  " + password);
 
 
            }
            //执行结束关闭连接
            reader.Close();
            coon.Close();
            Console.ReadKey();
       }
   }
11.用Mysql做插入操作
这里的话我们使用的是字符串组拼进行的数据库操作,但是这样的操作一个问题,可能会因为用户的恶意操作对数据库进行污染,类似于密码为deletefromuser这种
stringusername =
"haha";string password =
"111";
            MySqlCommand cmd =
new MySqlCommand("insert into user set username='" + username +
"'" +
",password='" + password +
"'",coon);
            //进行不查询的sql语句
            cmd.ExecuteNonQuery();
解决这个问题的方法就是用@进行注册变量,然后用AddWithValue来进行组拼
stringusername =
"haha";string password =
"111111";
            MySqlCommand cmd =
new MySqlCommand("insert into user setusername=@un,password=@pwd",coon);
            cmd.Parameters.AddWithValue("un", username);
            cmd.Parameters.AddWithValue("pwd", password);
删除和更新的话就是update和delete,操作和上面类似,就介绍到这里了
12.服务器的分层架构

13.初步创建我们的服务器端
这里我们创建出服务器的Socket,提供接受端口号和ip地址创建IpendPoint的方法,并且使用异步的方法接受客户端传递的值
namespace游戏服务器.Sever
{
   classSever
   {
       //这里的话,我们创建我们游戏的服务器端
       privateIPEndPoint ipEndpoint;
      private 
Socket severSocket;
       public Sever()
       {
 
       }
       //根据我们提供的Ip地址和端口号创立连接
       public Sever(string ipStr,int
port)
       {
            SetIpAndPort(ipStr, port);
       }
       publicvoid SetIpAndPort(string ipStr,int
port)
       {
            ipEndpoint =
newIPEndPoint(IPAddress.Parse(ipStr), port);
       }
       publicvoid Start()
       {
            severSocket =
newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            severSocket.Bind(ipEndpoint);
//表示最大连接长度为无限
            severSocket.Listen(0);
//接受客户端的连接
           severSocket.BeginAccept(AcceptCallBack,
null);
 
       }
//处理连接回调
       publicvoidAcceptCallBack(IAsyncResult ar)
       {
            Socket clientSocket =severSocket.EndAccept(ar);
       }
 
}
14.创建我们的客户端
这里的话是处理我们和服务器端的一些交互和客户端要处理的事物,首先,我们要在客户端里创建自身的socket,并且持有到Sever端的Socket,然后我们在Start调用BeginReceive开始异步接受服务器端传递的信息,这里对于粘包分包的问题我们放在其他类里进行处理,然后我们写回调函数来处理接受的,当接收到的信息为0的时候,我们就断开和服务器之间的连接,这里我们用tryCatch来捕捉异常。然后我们书写一个Close方法,来关闭连接,这里,在Sever端我们提供一个方法来移除客户端,当然要先lock再移除,以防止出错
using System;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
usingSystem.Net.Sockets;
usingSystem.Net;
 
namespace游戏服务器.Sever
{
   classClient
   {
       private SocketclientSocket;
       private Seversever;
 
       publicClient()
       {
 
       }
       publicClient(Socket clientSocket, Sever sever)
       {
            //持有一个对socket的引用
            clientSocket =
this.clientSocket;
            this.sever = sever;
       }
       //用来处理和服务器端之间的通信
       publicvoid Start()
       {
            clientSocket.BeginReceive(null, 0, 0,SocketFlags.None, ReceiveCallBack,
null);
 
       }
       publicvoidReceiveCallBack(IAsyncResult ar)
       {
            try
            {
                int count = clientSocket.EndReceive(ar);
                if (count == 0)
                {
                    Close();
                }
           }
 
            catch (Exception e)
            {
                Close();
                Console.WriteLine(e);
            }
 
       }
       publicvoid Close()
       {
            if (clientSocket !=
null)
            {
                clientSocket.Close();
                sever.RemoverClient(this);
            }
       }
   }
}
15.引入Messgae类来对信息进行处理
using System;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
 
namespace游戏服务器.Sever
{
   classMessage
   {
       //在这里专门创建一个方法,用来计算传递的字符串的长度,并且将它组拼成一个新的数组用来避免粘包的产生
       publicstaticbyte[] GetBytes(string
data)
       {
            //将字符串转变为数组
            byte[] databuf = Encoding.UTF8.GetBytes(data);
            //计算字节数组长度
            int datalength = databuf.Length;
            //将它转变为4个字节长度的字节数组用来计算长度
            byte[] countLength = BitConverter.GetBytes(datalength);
            //组拼成新的字节数组,即长度加原本的数组
            byte[] newByte = countLength.Concat(databuf).ToArray();
            return newByte;
       }
 
 
 
   }
}
16.完成Controller层的搭建
  首先,我们客户端向服务器发出的请求都是通过Controller层来进行处理的,这里来讲解一下如何初步搭建Controller层
   首先,我们要创建一个抽象基类BaseController,我们的子类都是继承自这个Controller,不同的需求对应不同的Controller
然后,我们创建一个Common的类库,这个是服务器端和客户端共享的代码,因为客户端向服务器端发出请求的时候,是通过RequestCode发送消息,而服务器端也需要这个RequestCode知道你调用的是哪一个Controller
这里我们创建一个枚举类型的RequestCode和ActionCode类
然后我们在BaseController里创建一个空的RequestCode和一个默认的实现方法
abstractclassBaseController
   {
       RequestCode requestCode = RequestCode.None;
 
       //子类可以选择性实现这个方法,这个是默认的处理方法
        publicvirtualvoid DefaultHandle()
       {
 
       }
    }
17.
这里来解释一下客户端和服务器端交互的原理
首先,当我们的客户端向服务器端发起了一个请求,比如注册,这时候我们会向服务器的Controller层发送一个数据长度+RequestCode+ActionCode+数据的这样一个信息,数据长度用来解决粘包分包的问题,RequestCode用来判断用哪一个Controller来执行,ActionCode用来判断用哪一个方法来解决这个请求,这两个Code都是int类型的四个字节的数据
然后我们的Controller层也会根据你的请求进行判断,如果是要做出响应的请求,服务器端就会向客户端回发一个数据长度+RequestCode+数据的信息,我们的客户端会根据对应的RequestCode进行相应的反应,比如注册请求的响应,就会回复一个注册成功
这里的话我们一个服务器端可以同时响应多个客户端的请求,而一个客户端只能回应一个服务器的RequestCode

18.创建我们的ControllerMannager
这里的话,我们需要一个类来管理我们的Controller,并且这个管理类为了避免冗余度过高,我们选择用Sever服务器端作为中介者,来进行交互
首先我们要一个字典,用来存储各种Controller,然后我们就要对它进行初始化了
namespace游戏服务器.Controller
{
   classControllerManager
   {
       //这个是用来管理Controller,来决定什么时候调用什么Controller
       //首先创建一个字典,用来存储各种Controller
       privateDictionary<RequestCode,BaseController> requestDictionary=newDictionary<RequestCode,BaseController>();
       publicControllerManager()
       {
            Init();
       }
       void Init()
       {
            //在这里进行初始化
       }
   }
}
这里我们在Sever构建一个接口,以后其他类想要使用ControllerMannager,都要通过Sever类来执行
private ControllerManagercontrollerManager =
newControllerManager();
19.通过ControllerMannager来处理分发的请求
首先,我们要提供一个DefaultController来判断当客户端传递的是没有ActionCode的时候来怎么处理,当然这里首先我们要在BaseController提供一个方法来获得它的RequestCode
publicRequestCode RequestCode
       {
            get
            {
                return RequestCode;
            }
        }
这样我们就可以在ControllerMannager里实例化DefaultController来进行错误处理了
void Init()
       {
            //给一个处理错误的Controller
            DefaultController defaultController=
newDefaultController();
           requestDictionary.Add(defaultController.RequestCode, defaultController);
        }
然后的话,我们就提供一个方法来处理客户端向服务器端请求Controller的方法,首先,我们要传递过来客户端发送的数据,请求的RequestCode和ActionCode,然后我们获得基类的Controller,根据tryGetValue来判断是否存在客户端请求的requestCode是否有对应的Controller,如果有的话,我们就要用Enum里的GetName,根据类型,来获得ActionCode里的值,再将其转变成为字符串类型,这里我们ActionCode里面定义的是None这个值类型,我们将其转换成字符串类型
接下来的话,我们运用的就是C#里的反射机制,通过controller.getType.getMethod,来根据方法名获取到方法信息,这里的话,我们需要引用一下System.Reflection
如果存在这个方法的话,我们就可以用MethodInfo里的invoke方法,来根据参数调用这个方法了,这里参数需要是object[]类型,我们转换一下就可以使用了前面的参数是指在什么下运行,我们指定为controller,这样的话,我们就可以调用方法了,当然这里有个返回值,判断方法调用是否需要给客户端做出回应,这个我们后面再讲
 
publicvoidHandleRequest(RequestCode requestCode,ActionCode actionCode,string data)
       {
            BaseController controller;
            //判断是否根据对应的RequestCode获取到对应的Controller
            bool isGet=requestDictionary.TryGetValue(requestCode,
out controller);
            if (isGet ==
false)
            {
                Console.WriteLine("无法获得到" + requestCode +
"对应的Controller");return;
            }
            //如果有对应的RequestCode的话,我们就要获取到对应的方法名,这里是获取到对应ActionCode里的值
            string methodName = Enum.GetName(typeof(ActionCode), actionCode);
            //这里是用到C#中的反射机制,将对应类型的对应的方法名的方法信息获得到
          MethodInfo mi= controller.GetType().GetMethod(methodName);
            if (mi ==
null)
            {
                Console.WriteLine("该方法" + methodName +
"不存在");
                return;
            }
            //在controller中调用
            object[] paramaters =
newobject[] { data };
            //根据o来判断是否响应
            object o= mi.Invoke(controller, paramaters);
 
       }
       
    }
19.处理客户端请求的响应
首先,我们BaseController默认的方法,传递的除了数据以外,还有对应的客户端和服务器端
  publicvirtualstring DefaultHandle(string
data,Clientclient,Sever sever)
       {
            //默认不给客户端返回数据
            returnnull;
        }
然后的话,我们在ControllerMannager中传递对应的服务器
  private Sever sever;
       publicControllerManager(Sever sever)
       {
            this.sever = sever;
            InitController();
        }
这样的话,在Sever端的构造函数里,我们就可以直接构造出ControllerManager并且将自身传递过去
  public Sever(string ipStr,int
port)
       {
            controllerManager =
new ControllerManager(this);
            SetIpAndPort(ipStr, port);
        }
然后我们怎么处理对客户端发送消息的响应呢,我们在Sever端里提供一个处理方法,SendMessage,用来作为客户端和ControllerManager的中介,通过这个方法来处理课都俺的信息
publicvoid SendMessage(Clientclient,RequestCode requestCode,string data)
       {
            //TODO
        }
这样我们就可以在ControllerManager里调用sever的这个方法来处理客户端的请求了
     object o=mi.Invoke(controller, paramaters);
            if (o ==
null || string.IsNullOrEmpty(o.ToString()))
            {
                //如果空就不进行处理
                return;
            }
            //通过sever端进行中介来发送数据
           sever.SendMessage(client, requestCode, o
asstring);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: