C#Socket创建3个实例?

时间:2017-03-25 16:46:18

标签: c#

我最近编写了一个套接字管理器,用于接收与我的游戏服务器的连接。每次客户端连接时,都会创建一个新的GameClient实例。问题是,目前正在创建3个GameClient实例,我不知道为什么。有人可以提供帮助,因为我只想要一个连接而且我真的不确定它为什么要创建3?

我的代码如下......

namespace Emulator.Core.Network.GameSockets
{
    using System;
    using System.Net;
    using System.Net.Sockets;
    using Base.Game.Habbo.Players.Players;
    using NLog;

    internal sealed class GameSocketManager : IDisposable
    {
        private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();

        private readonly Socket _gameSocket;

        public GameSocketManager()
        {
            _gameSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            Start();
        }

        private void Start()
        {
            var gameSocketPort = Convert.ToInt32(Config.GetConfigValueByKey("game.socket.port"));
            var gameSocketBacklog = Convert.ToInt32(Config.GetConfigValueByKey("game.socket.backlog"));

            _gameSocket.Bind(new IPEndPoint(IPAddress.Any, gameSocketPort));
            _gameSocket.Listen(gameSocketBacklog);
            _gameSocket.BeginAccept(OnAcceptConnection, _gameSocket);
        }

        private void OnAcceptConnection(IAsyncResult asyncResult)
        {
            try
            {
                if (_gameSocket == null)
                {
                    return;
                }

                var server = (Socket)asyncResult.AsyncState;
                var client = server.EndAccept(asyncResult);

                var uniqueId = Guid.NewGuid().ToString();
                var newPlayer = new GameClient(client, uniqueId);

                if (!GameManager.PlayerManager.TryAddPlayer(newPlayer))
                {
                    Logger.Error("Failed to register new player on " + client.RemoteEndPoint);
                }
            }
            catch (SocketException socketException)
            {
                Logger.Fatal("Failed to accept socket connection: " + socketException.Message);
                Logger.Fatal(socketException);
            }
            finally
            {
                _gameSocket?.BeginAccept(OnAcceptConnection, _gameSocket);
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }

        private void Dispose(bool disposing)
        {
            if (!disposing)
            {
                return;
            }

            if (_gameSocket == null)
            {
                return;
            }

            _gameSocket.Shutdown(SocketShutdown.Both);
            _gameSocket.Close();
            _gameSocket.Dispose();
        }
    }
}

GameClient:

public sealed class GameClient : GameClientData, IDisposable
    {
        private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();

        private readonly Socket _socket;
        private readonly byte[] _buffer;
        private readonly string _guid;
        private ARC4 _rc4Client;
        private PlayerTimer _playerTimer;
        private bool _disposing;

        internal GameClient(Socket socket, string guid)
        {
            _socket = socket;
            _socket.SendBufferSize = Convert.ToInt32(Hariak.HariakServer.Config.GetConfigValueByKey("packet.buffer.size"));
            _buffer = new byte[Convert.ToInt32(Hariak.HariakServer.Config.GetConfigValueByKey("packet.buffer.size"))];
            _guid = guid;

            PingCount = 0;

            Utilities = new PlayerUtilities(this);
            StartReceive();
        }

        private void StartReceive()
        {
            try
            {
                _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnDataReceived, _socket);
            }
            catch (SocketException exception)
            {
                Logger.Error(exception, "Failed to start receiving data on connection socket.");
                Dispose();
            }
        }

        private void ProcessPacketData(byte[] receivedData)
        {
            _rc4Client?.Decrypt(ref receivedData);

            var receivedDataPacketId = receivedData[0];

            if (receivedDataPacketId == 67)
            {
                return;
            }

            if (receivedDataPacketId == 60)
            {
                const string crossDomainPolicy = "<?xml version=\"1.0\"?>\r\n"
                    + "<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\r\n"
                    + "<cross-domain-policy>\r\n"
                    + "<site-control permitted-cross-domain-policies=\"master-only\"/>\r\n"
                    + "<allow-access-from domain=\"*\" to-ports=\"*\" />\r\n"
                    + "</cross-domain-policy>\x0";

                SendString(crossDomainPolicy);
            }
            else
            {
                using (var reader = new BinaryReader(new MemoryStream(receivedData)))
                {
                    if (receivedData.Length < 4)
                    {
                        return;
                    }

                    var packetLength = PacketUtilities.DecodeInt32(reader.ReadBytes(4));

                    if (reader.BaseStream.Length - 4 < packetLength)
                    {
                        return;
                    }

                    if (packetLength < 0 || packetLength > 5120)
                    {
                        return;
                    }

                    var packetBytes = reader.ReadBytes(packetLength);

                    using (var binaryReader = new BinaryReader(new MemoryStream(packetBytes)))
                    {
                        var packetHeader = PacketUtilities.DecodeInt16(binaryReader.ReadBytes(2));
                        var packetBodyBytes = new byte[packetBytes.Length - 2];

                        Buffer.BlockCopy(packetBytes, 2, packetBodyBytes, 0, packetBytes.Length - 2);

                        var packetEvent = new PacketEvent(packetHeader, packetBodyBytes);

                        if (!Hariak.HariakServer.GameManager.PacketManager.ProcessPacket(this, packetEvent))
                        {
                            Logger.Error("Failed to execute packet " + packetEvent.PacketId);
                        }
                    }

                    if (reader.BaseStream.Length - 4 <= packetLength)
                    {
                        return;
                    }

                    var extra = new byte[reader.BaseStream.Length - reader.BaseStream.Position];
                    Buffer.BlockCopy(receivedData, (int)reader.BaseStream.Position, extra, 0, (int)(reader.BaseStream.Length - reader.BaseStream.Position));

                    ProcessPacketData(extra);
                }
            }
        }

        private void OnDataReceived(IAsyncResult iAsyncResult)
        {
            try
            {
                var bytesReceived = _socket.EndReceive(iAsyncResult);

                if (bytesReceived == 0)
                {
                    return;
                }

                var packet = new byte[bytesReceived];
                Array.Copy(_buffer, packet, bytesReceived);
                ProcessPacketData(packet);
            }
            catch
            {
                Dispose();
            }
            finally
            {
                try
                {
                    _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnDataReceived, _socket);
                }
                catch
                {
                    Dispose();
                }
            }
        }

        internal void Authenticate(string sso)
        {
            try
            {
                if (!TryLoadGameClientData(this, sso))
                {
                    Dispose();
                    return;
                }

                _playerTimer = new PlayerTimer(this);

                //todo: ban checking
                //todo: load userstats

                SendComposer(new AuthenticationComposer());
                SendComposer(new AvatarEffectsComposer(Components.EffectComponent.PlayerEffects));
                SendComposer(new NavigatorSettingsComposer(SelectColumnInt("home_room")));
                //todo: FavouritesComposer
                //todo: FigureSetIdsComposer
                SendComposer(new UserRightsComposer(SelectColumnInt("rank")));
                SendComposer(new CheckAvailabilityComposer());
                //todo: AchievementScoreComposer
                SendComposer(new BuildersClubMembershipComposer());
                //todo: CfhTopicsInitComposer
                //todo: BadgeDefinitionsComposer
                //todo: SoundSettingsComposer

                UpdateColumn("machine_id", MachineId);

                //todo: give rank badge
                //todo: subscriptions

                Utilities.SendMotdNotification("Welcome message, using Hariak Emulator.");

                //todo: check rewards

                Logger.Info(SelectColumn("username") + " logged in");
            }
            catch (Exception exception)
            {
                Logger.Error(exception, "Error during player authentication.");
            }
        }

        internal void SendComposer(PacketComposer packetComposer)
        {
            Logger.Trace("Sending Composer: " + packetComposer.ComposerId);
            SendData(packetComposer.GetFinalBytes());
        }

        private void SendString(string data)
        {
            SendData(Encoding.UTF8.GetBytes(data));
        }

        internal void SendData(byte[] data)
        {
            try
            {
                _socket.BeginSend(data, 0, data.Length, 0, OnSend, null);
            }
            catch (SocketException socketException)
            {
                Logger.Error("Error sending message to socket: " + socketException.Message);
                Logger.Error(socketException);

                Dispose();
            }
        }

        private void OnSend(IAsyncResult asyncResult)
        {
            try
            {
                if (_socket == null)
                {
                    return;
                }

                _socket.EndSend(asyncResult);
            }
            catch (SocketException)
            {
                Dispose();
            }
        }

        internal ARC4 Rc4Client
        {
            set { _rc4Client = value; }
            get { return _rc4Client; }
        }

        internal string MachineId { private get; set; }

        internal PlayerUtilities Utilities { get; }

        internal string Guid => _guid;

        public void Dispose()
        {
            Dispose(true);
        }

        private void Dispose(bool disposing)
        {
            if (!disposing || _disposing)
            {
                return;
            }

            _disposing = true;

            _playerTimer?.Dispose();

            if (!Hariak.HariakServer.GameManager.PlayerManager.TryRemovePlayer(_guid))
            {
                Logger.Error("Failed to remove a players instance from PlayerManager.");
            }

            _socket.Shutdown(SocketShutdown.Both);
            _socket.Close();
        }
    }

0 个答案:

没有答案