一、Xamarin Studio
用于架设服务器的关键平台.
二、文件结构
三、代码
Program.cs
using System; using System.Net; using System.Net.Sockets; using System.Collections.Generic; using System.Reflection; using System.Linq; public class ClientState{ public Socket socket; //接收缓冲区 public byte[] readBuff = new byte[1024]; //接收缓冲区的数据长度 public int buffCount = 0; public int hp = -100; public float x = 0; public float y = 0; public float z = 0; public float eulY = 0; } class MainClass { //int buffCount = 0; //监听Socket static Socket listenfd; //客户端Socket及状态信息-----clients public static Dictionary<Socket,ClientState> clients =new Dictionary<Socket,ClientState>(); public static void Main(string[] args) { //Socket-----listenfd------监听端或称服务端 listenfd = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); //局域网IP处理 string hostName = Dns.GetHostName(); //获取主机名称 Console.WriteLine("主机:" + hostName); IPAddress[] addresses = Dns.GetHostEntry(Dns.GetHostName()).AddressList; //解析主机IP地址 Console.WriteLine("IP:" + addresses[1]); //Bind-------绑定服务端IP及端口 IPAddress ipAdr = IPAddress.Parse(addresses[1].ToString()); IPEndPoint ipEp = new IPEndPoint(ipAdr,8888); listenfd.Bind(ipEp); //Listen-------启动服务器并开启监听 listenfd.Listen(0); Console.WriteLine("[服务器]启动成功,并已开启监听!"); //checkRead-----------socket终端列表 List<Socket> checkRead = new List<Socket>(); Console.WriteLine("建立checkRead-----------socket终端列表"); //主循环-----等待触发 Console.WriteLine("开启主循环(不间断)-----等待触发"); while(true) { //填充checkRead列表 checkRead.Clear(); checkRead.Add(listenfd); //添加监听终端socket foreach(ClientState s in clients.Values) { checkRead.Add(s.socket);//添加客户端socket } //select---------多路复用,就是同时处理多路信号,比如同时检测多个Socket的状态。 Socket.Select(checkRead,null,null,1000); //检查可读对象 foreach(Socket s in checkRead) { if(s == listenfd) { ReadListenfd(s); } else{ ReadClientfd(s); } } } } //读取Listenfd------监听端信息 public static void ReadListenfd(Socket listenfd) { Console.WriteLine("读取Listenfd------监听端信息-------开启Accept"); Socket clientfd = listenfd.Accept(); ClientState state = new ClientState(); state.socket = clientfd; clients.Add(clientfd,state); } //读取Clientfd------客户端信息 public static bool ReadClientfd(Socket clientfd) { Console.WriteLine("读取Clientfd------客户端信息"); ClientState state = clients[clientfd]; //接收 int count = 0; //byte[] bufferTmp = new byte[1024]; try { count = clientfd.Receive(state.readBuff); } catch(SocketException ex) { MethodInfo mei = typeof(EventHandler).GetMethod("OnDisconnect"); object[] ob = { state }; mei.Invoke(null,ob); clientfd.Close(); clients.Remove(clientfd); Console.WriteLine("Receive SocketException " + ex.ToString()); return false; } //客户端关闭 if(count == 0) { MethodInfo mei = typeof(EventHandler).GetMethod("OnDisconnect"); object[] ob = { state }; mei.Invoke(null,ob); clientfd.Close(); clients.Remove(clientfd); Console.WriteLine("Socket Close"); return false; } //消息处理 MethodInfo mei1 = typeof(MainClass).GetMethod("DealWithMsg"); object[] ob1 = { state,count }; mei1.Invoke(null, ob1); return true; } public static void Send(ClientState c, string sendStr) { byte[] sendBytes = System.Text.Encoding.Default.GetBytes(sendStr); c.socket.Send(sendBytes); } public static void DealWithMsg(ClientState state,int buffCount) { Console.WriteLine("DealWithMsg!"); if (buffCount <= 2) return; Int16 bodyLength = BitConverter.ToInt16(state.readBuff, 0); //消息体长度 if (buffCount < 2 + bodyLength) return; //如果是完整的消息,就处理它 string s = System.Text.Encoding.UTF8.GetString(state.readBuff, 2, buffCount); //使用System.Text.Encoding.UTF8.GetString(缓冲区,开始位置,长度)将缓冲区的指定数据转换为字符串,读取消息内容。 string recvStr = s; string[] split = recvStr.Split(‘|‘); Console.WriteLine("Recv" + recvStr); string msgName = split[0]; string msgArgs = split[1]; string funName = "Msg" + msgName; MethodInfo mi = typeof(MsgHandler).GetMethod(funName); object[] o = { state, msgArgs }; mi.Invoke(null, o); //更新缓冲区 int start = 2 + bodyLength; int count = buffCount - start; Array.Copy(state.readBuff, start, state.readBuff, 0, count); buffCount -= start; //如果有更多消息,就处理它 if (state.readBuff.Length > 2) { DealWithMsg(state,buffCount); } } }
MsgHandler.cs
using System; using System.Collections.Generic; class MsgHandler { public static void MsgEnter(ClientState c,string msgArgs) { //解析参数 string[] split = msgArgs.Split(‘,‘); string desc = split[0]; float x = float.Parse(split[1]); float y = float.Parse(split[2]); float z = float.Parse(split[3]); float eulY = float.Parse(split[4]); //赋值 c.hp = 100; c.x = x; c.y = y; c.z = z; c.eulY = eulY; //广播 string sendStr = "Enter|" + msgArgs; foreach(ClientState cs in MainClass.clients.Values) { MainClass.Send(cs,sendStr); } Console.WriteLine("MsgEnter" + sendStr); } public static void MsgList(ClientState c,string msgArgs) { string sendStr = "List|"; foreach(ClientState cs in MainClass.clients.Values) { sendStr += cs.socket.RemoteEndPoint.ToString()+","; sendStr += cs.x.ToString()+","; sendStr += cs.y.ToString()+","; sendStr += cs.z.ToString()+","; sendStr += cs.eulY.ToString()+","; sendStr += cs.hp.ToString()+ ","; } MainClass.Send(c,sendStr); Console.WriteLine(c.socket.RemoteEndPoint.ToString()+","+"MsgList" + sendStr); } public static void MsgMove(ClientState c,string msgArgs) { //解析参数 string[] split = msgArgs.Split(‘,‘); string desc = split[0]; float x = float.Parse(split[1]); float y = float.Parse(split[2]); float z = float.Parse(split[3]); //赋值 c.x = x; c.y = y; c.z = z; //广播 string sendStr = "Move|" + msgArgs; foreach(ClientState cs in MainClass.clients.Values) { MainClass.Send(cs,sendStr); } } public static void MsgAttack(ClientState c,string msgArgs) { //广播 string sendStr = "Attack|" + msgArgs; foreach(ClientState cs in MainClass.clients.Values) { MainClass.Send(cs,sendStr); } } public static void MsgHit(ClientState c,string msgArgs) { //解析参数 string[] split = msgArgs.Split(‘,‘); string attDesc = split[0]; string hitDesc = split[1]; //找出被攻击的角色 ClientState hitCS = null; foreach(ClientState cs in MainClass.clients.Values) { if(cs.socket.RemoteEndPoint.ToString()== hitDesc) hitCS = cs; } if(hitCS == null)return; //扣血 hitCS.hp -= 25; //死亡 if(hitCS.hp <= 0) { string sendStr = "Die|" + hitCS.socket.RemoteEndPoint.ToString(); foreach(ClientState cs in MainClass.clients.Values) { MainClass.Send(cs,sendStr); } } } }
EventHandler.cs
using System; public class EventHandler { public static void OnDisconnect(ClientState c) { Console.WriteLine("OnDisconnect"); string desc = c.socket.RemoteEndPoint.ToString(); string sendStr = "Leave|" + desc + ","; foreach(ClientState cs in MainClass.clients.Values){ MainClass.Send(cs,sendStr); } } }
原文:https://www.cnblogs.com/guaike01/p/14494281.html