Unity3D 网络游戏框架(六、Select服务端Socket)

除了异步实现Socket之外,我们还有常用的方法,如Select,所以我们先了解什么是Select

参考连接:Socket.Select 方法 (System.Net.Sockets) | Microsoft Learn

阅读完之后,我来简要说明一下,这个方法有四个参数,我们关注第一个参数,它是一个List用来存客户端和服务端的Socket,如果有客户端连接过来那么服务端需要Accept,这就需要用到服务端Socket,所以服务端Socket会保存在List当中,而有客户端Socket发消息过来,我们的客户端Socket也会保存在List当中,这样这个List就收集到了需要AcceptSocket和需要ReceiveSocket,下面我们来看代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
#nullable disable
namespace UnityServer
{
    internal class Server
    {
        
        /// <summary>
        /// 服务端Socket
        /// </summary>
        private static Socket serverSocket;
        /// <summary>
        /// 客户端Socket以及状态信息的字典
        /// </summary>
        private static Dictionary<Socket, ClientState> clients = new Dictionary<Socket, ClientState>();
        public static void Main()
        {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ip = IPAddress.Parse("127.0.0.1");
            IPEndPoint iPEndPoint = new IPEndPoint(ip, 8888);
            serverSocket.Bind(iPEndPoint);
            serverSocket.Listen(0);

            Console.WriteLine("服务端启动成功");
            List<Socket> socketList = new List<Socket>();
            while (true)
            {
                socketList.Clear();
                socketList.Add(serverSocket);
                foreach (ClientState s in clients.Values)
                {
                    socketList.Add(s.socket);
                }

                //检测可读Socket
                Socket.Select(socketList, null, null, 1000);
                foreach (Socket s in socketList)
                {
                    if (s == serverSocket)
                    {
                        Accept(s);
                    }
                    else
                    {
                        Receive(s);
                    }
                }
            }
        }
        /// <summary>
        /// 服务端Accept
        /// </summary>
        /// <param name="serverSocket"></param>
        private static void Accept(Socket serverSocket)
        {
            Console.WriteLine("Accept");
            Socket clientSocket = serverSocket.Accept();
            ClientState state = new ClientState();
            state.socket = clientSocket;
            clients.Add(clientSocket,state);
        }
        /// <summary>
        /// 接收消息以及发送给所有客户端
        /// </summary>
        /// <param name="clientSocket"></param>
        private static void Receive(Socket clientSocket)
        {
            ClientState state = clients[clientSocket];
            int count = clientSocket.Receive(state.readBuff);
            //关闭
            if (count == 0)
            {
                clientSocket.Close();
                clients.Remove(clientSocket);
                Console.WriteLine("有一个客户端断开连接");
                return;
            }
            //发送给所有客户端
            string receiveStr = Encoding.UTF8.GetString(state.readBuff, 0, count);
            Console.WriteLine("Receive:" + receiveStr);

            byte[] sendBytes=Encoding.UTF8.GetBytes(receiveStr);
            foreach (ClientState s in clients.Values)
            {
                s.socket.Send(sendBytes);
            }
        }
    }
}

为了Select和异步都学会,我们采用Select服务端和异步客户端

猜你喜欢

转载自blog.csdn.net/qq_39596597/article/details/127582588