Godot服务器 C#
侧边栏壁纸
博主昵称

  • 累计撰写 3 篇文章
  • 累计收到 0 条评论

Godot服务器 C#

chnenuo
2025-09-16 / 0 评论 / 5 阅读 / 正在检测是否收录...
using System;
using System.Net;
using System.Net.Sockets;
using AI.scripts.Managers.Server.Net;
using Godot;
using Protocol.Dto;
using 框架.Event;
using Semaphore = System.Threading.Semaphore;

namespace 服务器.Server.Net;

public class ServerPeer
{
    private Socket _socket;
    private Semaphore _semaphore;
    private ClientPeerPool _clientPeerPool;
    private IApplication _application;

    public void SetApplication(IApplication application)
    {
        _application = application;
    }

    public void StartServer(string ip, int port, int maxClients)
    {
        try
        {
            _clientPeerPool = new ClientPeerPool(maxClients);
            _semaphore = new Semaphore(maxClients, maxClients);
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            // 创建初始化客户端池
            for (var i = 0; i < maxClients; i++)
            {
                ClientPeer clientPeer = new ClientPeer();
                EventCenter.Instance.AddEventListener<ClientPeer, NetMsg>("Receive", ReceiveProcess);
                clientPeer.ReceiveArgs.Completed += ReceiveArgsOnCompleted;
                _clientPeerPool.Enqueue(clientPeer);
            }

            _socket.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
            _socket.Listen(maxClients);

            GD.Print("[服务器]启动");
            AcceptClient();
        }
        catch (SocketException e)
        {
            GD.PrintErr($"[服务器]报错位置:StartServer {e.Message}");
        }
    }


    #region 接收客户端连接

    /// <summary>
    /// 接受客户端连接
    /// </summary>
    /// <param name="e"></param>
    private void AcceptClient(SocketAsyncEventArgs e = null)
    {
        if (e == null)
        {
            e = new SocketAsyncEventArgs();
            e.Completed += EOnCompleted;
        }

        var result = _socket.AcceptAsync(e);
        if (result == false)
        {
            ProcessAccept(e);
        }
    }

    /// <summary>
    /// 处理客户端连接完成事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void EOnCompleted(object sender, SocketAsyncEventArgs e)
    {
        ProcessAccept(e);
    }


    /// <summary>
    /// 处理客户端连接
    /// </summary>
    /// <param name="e"></param>
    private void ProcessAccept(SocketAsyncEventArgs e)
    {
        _semaphore.WaitOne();
        ClientPeer client = _clientPeerPool.Dequeue();
        client.ClientSocket = e.AcceptSocket;

        GD.Print($"[服务器]{client.ClientSocket?.RemoteEndPoint} 客户端连入");
        StartReceive(client);

        e.AcceptSocket = null;
        AcceptClient(e);
    }

    #endregion

    #region 接收数据

    private void StartReceive(ClientPeer client)
    {
        try
        {
            var result = client.ClientSocket.ReceiveAsync(client.ReceiveArgs);
            if (result == false)
            {
                ProcessReceive(client.ReceiveArgs);
            }
        }
        catch (SocketException e)
        {
            GD.PrintErr($"[服务器]报错位置:StartReceive  {e.Message}");
        }
    }

    /// <summary>
    /// 处理接收数据完成事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ReceiveArgsOnCompleted(object sender, SocketAsyncEventArgs e)
    {
        ProcessReceive(e);
    }

    /// <summary>
    /// 处理接收数据
    /// </summary>
    /// <param name="e"></param>
    private void ProcessReceive(SocketAsyncEventArgs e)
    {
        var client = e.UserToken as ClientPeer;
        if (client?.ReceiveArgs.SocketError == SocketError.Success && client.ReceiveArgs.BytesTransferred > 0)
        {
            var packet = new byte[client.ReceiveArgs.BytesTransferred];
            if (client.ReceiveArgs.Buffer == null) return;
            Buffer.BlockCopy(client.ReceiveArgs.Buffer, 0, packet, 0,
                client.ReceiveArgs.BytesTransferred);

            client.ProcessReceive(packet);
            StartReceive(client);
        }
        else //断开连接
        {
            if (client?.ReceiveArgs.BytesTransferred == 0)
            {
                // 主动断开连接
                if (client.ReceiveArgs.SocketError == SocketError.Success)
                {
                    DisconnectClient(client, "主动断开连接");
                }
                else if (client.ReceiveArgs.SocketError == SocketError.ConnectionReset)
                {
                    DisconnectClient(client, client.ReceiveArgs.SocketError.ToString());
                }
            }
        }
    }

    /// <summary>
    /// 处理一条消息
    /// </summary>
    /// <param name="client"></param>
    /// <param name="msg"></param>
    private void ReceiveProcess(ClientPeer client, NetMsg msg)
    {
       
        // 应用层 处理消息
        _application.Receive(client, msg);
    }

    #endregion

    #region 断开连接

    /// <summary>
    /// 断开客户端连接
    /// </summary>
    /// <param name="client"></param>
    /// <param name="reason"></param>
    private void DisconnectClient(ClientPeer client, string reason)
    {
        try
        {
            if (client == null)
                GD.PrintErr("客户端为空");
            GD.Print($"[服务器]{client.ClientSocket?.RemoteEndPoint}客户端断开连接:{reason}");
            _application.Disconnect(client);
            //客户端断开连接
            client.Disconnect();
            //将断开连接的客户端添加到客户端池中
            _clientPeerPool.Enqueue(client);
            //释放信号量
            _semaphore.Release();
        }
        catch (SocketException e)
        {
            GD.PrintErr($"[服务器]报错位置:DisconnectClient {e.Message}");
        }
    }

    #endregion
}
0

评论

博主关闭了所有页面的评论