区分消息类型_服务端

67 阅读3分钟

那四个脚本需要放在服务器程序中去(BaseData、PlayerData、baseMsg、PlayerMsg)

image.png

主要修改的类:服务端启动类ServerSocket和序列化和反序列化类ClientSocket和Main函数类

序列化和反序列化类ClientSocket

首先修改的是ClientSocket:
需要修改成BaseMsg 的接收和发送
Send(string info)方法参数修改  socket.Send(Encoding.UTF8.GetBytes(info));发送的数据类型修改
这两句代码修改成
 Send(BaseMsg info) 
 socket.send(info.Writing());
 
 接收:
 需要将线程池中的方法 
  //先拿到消息ID
 int msgID=BitConverter.ToInt32(result, 0);
 BaseMsg msg = null;
 然后使用Switch进行判断ID 再进行反序列化  
 msg = new PlayerMsg();
 msg.Reading(result,4);break;}
 再将
 ThreadPool.QueueUserWorkItem(MsgHandle,Encoding.UTF8.GetString(result,0,receiveNum));
 修改成 参数为BaseMsg类型数据
 ThreadPool.QueueUserWorkItem(NewMsgHandle, msg);
 NewMsgHandle方法中进行打印客户端发过来的消息
 public void NewMsgHandle(object obj)
{
    BaseMsg msg = (BaseMsg)obj;
    //进行判断  msg的结构类型
    if(msg is PlayerMsg)
    {
        PlayerMsg playerMsg = (PlayerMsg)msg;
        Console.WriteLine(playerMsg.playerID);
        Console.WriteLine(playerMsg.playerData.name);
        Console.WriteLine(playerMsg.playerData.atk);
        Console.WriteLine(playerMsg.playerData.lev);
    }
}

服务端启动类ServerSocket

  只需要修改广播方法
  
  Broadcast(string info)将Broadcast(BaseMsg info)

主函数Program

 修改广播发送数据方式
 

image.png

ClientSocket代码

using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace TeachTcpExcise3qufenxiaoxi
{
    class ClientSocket
    {
        private static int CLIENT_BEGIN_ID = 1;  //初始ID等于1
        public int clientID;  //设置每个客户端的ID
        public Socket socket;

        //每次调用的时候会进行 自增 记录Socket
        public ClientSocket(Socket socket)
        {
            this.clientID = CLIENT_BEGIN_ID;
            this.socket = socket;
            ++CLIENT_BEGIN_ID;
        }

        /// <summary>
        /// 可以从外部获取连接状态
        /// </summary>
        public bool isConnect => this.socket.Connected;
        //封装  一些方法
        //关闭
        public void close()
        {
            if (socket != null)
                return;
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            socket = null;
        }

        //发送
        public void send(BaseMsg info)
        {
            if (socket != null)
            {
                try
                {
                    socket.Send(info.Writing());
                }
                catch (Exception e)
                {
                    Console.WriteLine("发消息出错:"+e.Message);
                    close();
                }
            }
        }
        //接收
        public void receive()
        {
            
            try
            {
                if (socket.Available > 0)
                {
                    byte[] result = new byte[1024 * 5];
                    int receiveNum = socket.Receive(result);
                    //只接收字符串 线程池去接收处理发过来的消息
                    //ThreadPool.QueueUserWorkItem(MsgHandle,Encoding.UTF8.GetString(result,0,receiveNum));

                    //区分消息 接收消息  处理发过来的消息
                    //先拿到消息ID
                    int msgID=BitConverter.ToInt32(result, 0);
                    BaseMsg msg = null;
                    switch (msgID)
                    {
                        case 1001:
                            msg = new PlayerMsg();
                            msg.Reading(result,4);  //解析 拿到数据 然后在 线程中进行处理
                            break;
                    }
                    ThreadPool.QueueUserWorkItem(NewMsgHandle, msg);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("收消息出错:"+e.Message);
                close();
            }
        }

        //配套接收字符串 多线程
        /*public void MsgHandle(object obj)
        {
            string str = (string)obj;
            Console.WriteLine("收到客户端{0}发来的消息:{1}",this.socket.RemoteEndPoint,str);
        }*/

        public void NewMsgHandle(object obj)
        {
            BaseMsg msg = (BaseMsg)obj;
            //进行判断  msg的结构类型
            if(msg is PlayerMsg)
            {
                PlayerMsg playerMsg = (PlayerMsg)msg;
                Console.WriteLine(playerMsg.playerID);
                Console.WriteLine(playerMsg.playerData.name);
                Console.WriteLine(playerMsg.playerData.atk);
                Console.WriteLine(playerMsg.playerData.lev);
            }
        }



    }
}

ServerSocket代码

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace TeachTcpExcise3qufenxiaoxi
{
    class ServerSocket
    {

        //服务端Socket
        public Socket socket;
        //客户端连接的所有Socket
        public Dictionary<int, ClientSocket> clientDic = new Dictionary<int, ClientSocket>();

        //有待移除的客户端socket 避免 在foreach时直接从字典中移除 出现问题
        private List<ClientSocket> delList = new List<ClientSocket>();

        private bool isClose;

        //开启服务器端
        public void Start(string ip, int port, int num)
        {
            isClose = false;
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), port);
            socket.Bind(ipPoint);
            socket.Listen(num);
            ThreadPool.QueueUserWorkItem(Accept);
            ThreadPool.QueueUserWorkItem(Receive);
        }

        //关闭服务器端
        public void Close()
        {
            isClose = true;
            foreach (ClientSocket client in clientDic.Values)
            {
                client.close();
            }
            clientDic.Clear();

            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            socket = null;
        }

        //接受客户端连入
        private void Accept(object obj)
        {
            while (!isClose)
            {
                try
                {
                    //连入一个客户端
                    Socket clientSocket = socket.Accept();
                    ClientSocket client = new ClientSocket(clientSocket);
                   /* lock (clientDic)*/
                    clientDic.Add(client.clientID, client);
                }
                catch (Exception e)
                {
                    Console.WriteLine("客户端连入报错" + e.Message);
                }
            }
        }
        //接收客户端消息
        private void Receive(object obj)
        {
            while (!isClose)
            {
                if (clientDic.Count > 0)
                {
                    /* lock (clientDic)
                     {
                         foreach (ClientSocket client in clientDic.Values)
                         {
                             client.receive();
                         }

                         //CloseDelListSocket();
                     }*/
                    //判断字典容器的客户端Socket是否存在
                    
                        //进行遍历接受消息
                        foreach (ClientSocket client in clientDic.Values)
                        {
                            client.receive();
                        }
                    
                }
            }
        }

        public void Broadcast(BaseMsg info)
        {
            lock (clientDic)
            {
                foreach (ClientSocket client in clientDic.Values)
                {
                    client.send(info);
                }
            }

        }

        //添加待移除的 socket内容
        public void AddDelSocket(ClientSocket socket)
        {
            if (!delList.Contains(socket))
                delList.Add(socket);
        }

        /*////判断有没有 断开连接的 把其 移除
        public void CloseDelListSocket()
        {
            //判断有没有 断开连接的 把其 移除
            for (int i = 0; i < delList.Count; i++)
                CloseClientSocket(delList[i]);
            delList.Clear();
        }

        //关闭客户端连接的 从字典中移除
        public void CloseClientSocket(ClientSocket socket)
        {
            lock (clientDic)
            {
                socket.close();
                if (clientDic.ContainsKey(socket.clientID))
                {
                    clientDic.Remove(socket.clientID);
                    Console.WriteLine("客户端{0}主动断开连接了", socket.clientID);
                }
            }
        }*/
    }
}

Program 主函数

{
    internal class Program
    {
        static void Main(string[] args)
        {
            //在这主函数里面调用 谁的功能写在自身脚本中
            ServerSocket socket = new ServerSocket();
            socket.Start("127.0.0.1", 8080, 1024);
            Console.WriteLine("服务器开启成功");
            while (true)
            {
                string input = Console.ReadLine();
                if (input == "Quit")
                {
                    socket.Close();
                }
                else if (input.Substring(0, 2) == "B:")
                {
                    //广播
                    if (input.Substring(2) == "1001")
                    {
                        PlayerMsg msg = new PlayerMsg();
                        msg.playerID = 99;
                        msg.playerData = new PlayerData();
                        msg.playerData.name = "王者";
                        msg.playerData.atk = 990;
                        msg.playerData.lev = 99;
                        socket.Broadcast(msg);
                    }
                    
                }
            }
        }
    }
}