using UnityEngine; using System; using System.Collections.Generic; using AX.Network.Common; using AX.Network.Protocols; using IAppSession = AX.Network.Common.IAppSession; namespace AX.NetworkSystem { public static class NetworkMessageDispatcher { private static Dictionary> handlers = new Dictionary>(); private static ObjectPool messagePool = new ObjectPool(8, () => new BinaryMessage()); private static DynamicBufferPool bufferPool = new DynamicBufferPool(); private static Queue messages = new Queue(); private static Action connectedHandler; private static Action closedHandler; private static Queue connectedMessages = new Queue(); private static Queue> closedMessages = new Queue>(); private static object lockObj = new object(); public static void Update() { lock (lockObj) { while (messages.Count != 0) { var message = messages.Dequeue(); Action action; if (handlers.TryGetValue(message.Header, out action)) action(message); else { if (Application.isEditor) Debug.LogError("[NetworkSystem] 该消息类型 { " + message.Header + " } 没有对应的接收方处理。"); } if (message.Body != null) { Array.Clear(message.Body, 0, message.Body.Length); bufferPool.Release(message.Body); } message.Header = null; message.Body = null; message.Tag = null; messagePool.Release(message); } while (connectedMessages.Count != 0) { var connectedMessage = connectedMessages.Dequeue(); if (connectedHandler != null) connectedHandler((IAppSession)connectedMessage); } while (closedMessages.Count != 0) { var closedMessage = closedMessages.Dequeue(); if (closedHandler != null) closedHandler((IAppSession)closedMessage.Key, closedMessage.Value); } } } public static void Clear() { handlers.Clear(); messagePool.Clear(); bufferPool.Clear(); messages.Clear(); } public static void AddListener(string messageType, Action handler) { if (handlers.ContainsKey(messageType)) handlers[messageType] += handler; else handlers[messageType] = handler; } public static void RemoveListener(string messageType, Action handler) { if (handlers.ContainsKey(messageType)) { handlers[messageType] -= handler; if (handlers[messageType] == null) handlers.Remove(messageType); } } public static void AddConnectedListener(Action action) { connectedHandler += action; } public static void RemoveConnectedListener(Action action) { connectedHandler -= action; } public static void AddClosedListener(Action action) { closedHandler += action; } public static void RemoveClosedListener(Action action) { closedHandler -= action; } public static void SendMessage(BinaryMessage message, object tag = null) { if (message == null) return; lock (lockObj) { var binaryMessage = messagePool.Acquire(); binaryMessage.Header = message.Header; if (!message.RawBody.IsEmpty()) { binaryMessage.Body = bufferPool.Acquire(message.RawBody.Count); message.RawBody.CopyTo(binaryMessage.Body); } binaryMessage.Tag = tag; messages.Enqueue(binaryMessage); } } public static void SendMessage(string header) { lock (lockObj) { var binaryMessage = messagePool.Acquire(); binaryMessage.Header = header; messages.Enqueue(binaryMessage); } } public static void SendMessage(string header, object tag) { lock (lockObj) { var binaryMessage = messagePool.Acquire(); binaryMessage.Header = header; binaryMessage.Tag = tag; messages.Enqueue(binaryMessage); } } public static void SendMessage(string header, byte[] body, object tag = null) { lock (lockObj) { var binaryMessage = messagePool.Acquire(); binaryMessage.Header = header; binaryMessage.Body = body; binaryMessage.Tag = tag; messages.Enqueue(binaryMessage); } } public static void SendMessage(string header, ArraySegment body, object tag = null) { lock (lockObj) { var binaryMessage = messagePool.Acquire(); binaryMessage.Header = header; if (body.Array != null && body.Count != 0) { binaryMessage.Body = bufferPool.Acquire(body.Count); Buffer.BlockCopy(body.Array, body.Offset, binaryMessage.Body, 0, body.Count); } binaryMessage.Tag = tag; messages.Enqueue(binaryMessage); } } public static void SendConnectedMessage(object session) { if (session == null) return; lock (lockObj) { connectedMessages.Enqueue(session); } } public static void SendClosedMessage(KeyValuePair pair) { if (pair.Key == null) return; lock (lockObj) { closedMessages.Enqueue(pair); } } } }