using System; using System.Collections.Generic; using System.Net; using System.Threading; using UnityEngine; namespace BF { internal partial class TCPChannelService { private readonly Dictionary connections = new Dictionary(); private bool quitFlag = false; private readonly ManualResetEvent quitEvent = new ManualResetEvent(false); private void NetworkLoop() { while (!quitFlag) { WaitHandle.WaitAny(new WaitHandle[] { quitEvent}, 2); UpdateAsyncCommandMethod(); UpdateConnections(); } Debug.LogWarning($"{configuration.ThreadName} thread quit !!!"); } private void UpdateConnections() { foreach (var connection in connections) { connection.Value.Update(); } } private void UpdateAsyncCommandMethod() { try { while (commandMethodQueue.TryDequeue(out var currentMethod)) { AsyncCommandMethodExecute(currentMethod); } } catch (Exception exception) { mainThreadResetEvent.Set(); Debug.LogException(exception); } } private void AsyncCommandMethodExecute(BaseCommandMethod currentMethod) { switch (currentMethod.Command) { case CommandCategory.Shutdown: { ShutdownAllConnections(); break; } case CommandCategory.ConnectDomainName: { var method = currentMethod as ConnectDomainNameMethod; ConnectInternal(method.Configuration, method.DomainName, method.Port); break; } case CommandCategory.ConnectIPAddress: { var method = currentMethod as ConnectIPAddressMethod; ConnectInternal(method.Configuration, method.IpAddress, method.Port); break; } case CommandCategory.Reconnect: { var method = currentMethod as ReconnectMethod; ReconnectInternal(method.UniqueIdentifier); break; } case CommandCategory.Close: { var method = currentMethod as CloseMethod; CloseInternal(method.UniqueIdentifier); break; } case CommandCategory.GetConnectStatus: { var method = currentMethod as GetConnectStatusMethod; method.Result = GetConnectStatusInternal(method.UniqueIdentifier); break; } case CommandCategory.CreateMessage: { var method = currentMethod as CreateMessageMethod; method.Result = CreateMessageInternal(method.UniqueIdentifier); break; } case CommandCategory.SendMessage: { var method = currentMethod as SendMessageMethod; method.Result = SendInternal(method.UniqueIdentifier, method.Message); break; } case CommandCategory.SendRaw: { var method = currentMethod as SendRawMethod; method.Result = SendInternal(method.UniqueIdentifier, method.Group, method.CMD, method.Data); break; } case CommandCategory.ReadMessage: { var method = currentMethod as ReadMessageMethod; method.Result = ReadMessageInternal(method.UniqueIdentifier); break; } case CommandCategory.RecycleMessage: { var method = currentMethod as RecycleMessageMethod; RecycleMessageInternal(method.UniqueIdentifier, method.Message); break; } case CommandCategory.GetConnectIP: { var method = currentMethod as GetConnectIPMethod; method.Result = GetConnectIPInternal(method.UniqueIdentifier); break; } case CommandCategory.GetServerTimestamp: { var method = currentMethod as GetConnectServerTimestampMethod; method.Result = GetConnectServerTimestampInternal(method.UniqueIdentifier); break; } default: break; } mainThreadResetEvent.Set(); } #region Internal Method private void ConnectInternal(NetConnectConfiguration configuration, string domainName, int port) { INetConnection connection = GetConnection(configuration.UniqueIdentifier); if (connection != null) { return; } connection = new TCPConnection(configuration); connection.Connect(domainName, port); AddConnection(configuration.UniqueIdentifier, connection); } private void ConnectInternal(NetConnectConfiguration configuration, IPAddress ipAddress, int port) { INetConnection connection = GetConnection(configuration.UniqueIdentifier); if (connection != null) { return; } connection = new TCPConnection(configuration); connection.Connect(ipAddress, port); AddConnection(configuration.UniqueIdentifier, connection); } private void ReconnectInternal(string uniqueIdentifier) { INetConnection connection = GetConnection(uniqueIdentifier); connection?.Reconnect(); } private void CloseInternal(string uniqueIdentifier) { INetConnection connection = GetConnection(uniqueIdentifier); connection?.Close(); RemoveConnection(uniqueIdentifier); } private NetConnectStatus GetConnectStatusInternal(string uniqueIdentifier) { INetConnection connection = GetConnection(uniqueIdentifier); if (connection != null) { return connection.ConnectStatus; } return NetConnectStatus.InvalidConnect; } private string GetConnectIPInternal(string uniqueIdentifier) { INetConnection connection = GetConnection(uniqueIdentifier); if (connection == null) { return string.Empty; } if (connection.IpEndPoint == null) { return string.Empty; } return connection.IpEndPoint.Address.ToString(); } private long GetConnectServerTimestampInternal(string uniqueIdentifier) { INetConnection connection = GetConnection(uniqueIdentifier); if (connection == null) { return 0; } return connection.ServerTimestamp; } private INetOutgoingMessage CreateMessageInternal(string uniqueIdentifier) { INetConnection connection = GetConnection(uniqueIdentifier); return connection?.CreateMessage(); } private NetSendResult SendInternal(string uniqueIdentifier, INetOutgoingMessage message) { INetConnection connection = GetConnection(uniqueIdentifier); return connection.Send(message); } private NetSendResult SendInternal(string uniqueIdentifier, uint group, byte cmd, byte[] data) { INetConnection connection = GetConnection(uniqueIdentifier); return connection.Send(group, cmd, data); } private INetIncomingMessage ReadMessageInternal(string uniqueIdentifier) { INetConnection connection = GetConnection(uniqueIdentifier); return connection?.ReadMessage(); } private void RecycleMessageInternal(string uniqueIdentifier, INetIncomingMessage message) { INetConnection connection = GetConnection(uniqueIdentifier); connection?.RecycleMessage(message); } #endregion #region Utility private INetConnection GetConnection(string uniqueIdentifier) { connections.TryGetValue(uniqueIdentifier, out var connection); return connection; } private void AddConnection(string uniqueIdentifier, INetConnection connection) { connections.Add(uniqueIdentifier, connection); } private void RemoveConnection(string uniqueIdentifier) { connections.Remove(uniqueIdentifier); } private void ShutdownAllConnections() { foreach (var connection in connections) { connection.Value.Close(); } connections.Clear(); } #endregion } }