Unity3D 网络游戏框架(五、异步服务端Socket)

在之前的代码中,我们了解了如何开发异步客户端Socket,现在开发异步服务端Socket就轻松了

首先我们还是先查看一下微软官方文档的API了解下面的几个方法:

1、Socket.BeginAccept()

2、Socket.EndAccept()

3、Socket.BeginReceive()

4、Socket.EndReceive()

5、Socket.BeginSend()

6、SocketEndSend()

参考连接:Socket 类 (System.Net.Sockets) | Microsoft Learn

我们还需要一个存客户端信息的类ClientState,目前里面只需要一个客户端Socket和一个缓冲区数组

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
#nullable disable
namespace UnityServer
{
    internal class ClientState
    {
        /// <summary>
        /// 客户端socket
        /// </summary>
        public Socket socket;
        /// <summary>
        /// 接收缓冲区
        /// </summary>
        public byte[] readBuff=new byte[1024];
    }
}
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
    {
        static string receiveStr = "";
        /// <summary>
        /// 服务端socke
        /// </summary>
        static Socket serverSocket;
        /// <summary>
        /// 客户端socket以及客户端信息的字典
        /// </summary>
        static Dictionary<Socket, ClientState> clients = new Dictionary<Socket, ClientState>();
        public static void Main()
        {
            //定义socket
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //绑定ip和端口
            IPAddress ip = IPAddress.Parse("127.0.0.1");
            IPEndPoint iPEndPoint = new IPEndPoint(ip, 8888);
            serverSocket.Bind(iPEndPoint);
            //监听
            serverSocket.Listen(0);
            Console.WriteLine("服务端启动成功");
            serverSocket.BeginAccept(AcceptCallback, serverSocket);
            Console.ReadLine();
        }
        /// <summary>
        /// 应答回调
        /// </summary>
        /// <param name="ar"></param>
        private static void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                Socket serverSocket = ar.AsyncState as Socket;
                Socket clientSocket = serverSocket.EndAccept(ar);
                //创建客户端的ClientState以及添加字典
                ClientState state = new ClientState();
                state.socket = clientSocket;
                clients.Add(clientSocket, state);

                Console.WriteLine("有一个客户端Accept");
                clientSocket.BeginReceive(state.readBuff, 0, 1024, 0, ReceiveCallback, state);
                serverSocket.BeginAccept(AcceptCallback, serverSocket);
            }
            catch (SocketException ex)
            {
                Console.WriteLine("应答失败" + ex.ToString());
            }
        }
        /// <summary>
        /// 接收回调
        /// </summary>
        /// <param name="ar"></param>
        private static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                ClientState state = ar.AsyncState as ClientState;
                Socket clientSocket = state.socket;
                int count = clientSocket.EndReceive(ar);
                //客户端的关闭
                if (count == 0)
                {
                    clientSocket.Close();
                    clients.Remove(clientSocket);
                    Console.WriteLine("客户端断开连接");
                    return;
                }
                receiveStr = Encoding.UTF8.GetString(state.readBuff, 0, count);
                Console.WriteLine(receiveStr);

                foreach (ClientState s in clients.Values)
                {
                    s.socket.BeginSend(Encoding.UTF8.GetBytes(receiveStr), 0, receiveStr.Length, 0, SendCallback, clientSocket);
                }
                clientSocket.BeginReceive(state.readBuff, 0, 1024, 0, ReceiveCallback, state);
            }
            catch (SocketException ex)
            {
                Console.WriteLine("接收失败" + ex.ToString());
            }
        }
        /// <summary>
        /// 发送回调
        /// </summary>
        /// <param name="ar"></param>
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket clientSocket = ar.AsyncState as Socket;
                clientSocket.EndSend(ar);
            }
            catch (SocketException ex)
            {
                Console.WriteLine("发送失败" + ex.ToString());
            }
        }
        
    }
}

 这里用字典来储存客户端信息以及对应Socket,后面的基本逻辑和之前同步的一样,只不过都改成异步方法

这里面为了实现给多个客户端发送,我们遍历字典里面所有客户端就可以了

注意:这里面结尾的Console.ReadLine(),因为我们是异步接收,是子线程进行,如果没有这句话,主线程会直接结束

猜你喜欢

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