using System; using MrWu.Debug; using Server; using WebSocketSharp.Server; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using GameMessage; using MessagePack; using MrWu; using Server.Core; namespace Server.Net { public class NetManager : SingleInstance, IDisposable { public static bool isStart { get; private set; } public bool IsDispose { get; private set; } private WebSocketServer _webSocketServer; /// /// 会话集合 /// private ConcurrentDictionary sessionDic = new ConcurrentDictionary(); /// /// SessionIds 队列 /// private readonly ConcurrentQueue sessionIds = new ConcurrentQueue(); /// /// 当前的链接数 /// public int ConnectCount { get { return sessionDic.Count; } } /// /// 当前接收的数量 /// public long ReceiveCount; public const int MaxMessageSize = 1024*1024; /// /// 启动网络 /// public void Start(string webPath,int webPort) { if (!string.IsNullOrEmpty(webPath) && webPort > 0) { //webSocket 服务 启动 WChannel.OnConnectedEvt += WConnected; WChannel.OnDisconnectedEvt += WDisconnected; WChannel.OnReceivedEvt += WReceived; WChannel.OnErrorEvt += WError; _webSocketServer = new WebSocketServer(webPort); _webSocketServer.AddWebSocketService(webPath); _webSocketServer.Start(); //webSocket 服务 结束 isStart = true; } SessionUUIDManager.Instance.Init(); } public void Dispose() { IsDispose = true; WebSocketStop(); } private void WebSocketStop() { Task.Factory.StartNew(() => { _webSocketServer?.Stop(); }); } #region WebSocket 事件 private void WConnected(WChannel channel) { Session session = new Session(channel); Interlocked.Exchange(ref session.ReadWriteTime,TimeInfo.Instance.FrameTime); long id = session.Id; channel.SessionId = id; if (!sessionDic.TryAdd(id, session)) { Debug.Error("添加 webSocket 链接到 字典失败!!!"); } else { sessionIds.Enqueue(id); } } private void WDisconnected(WChannel channel) { long sessionId = channel.SessionId; if (sessionDic.TryRemove(sessionId,out Session session)) { session.OnDisConnected(); } else { Debug.Error("webSocket断开连接,竟然未找到 session!"); } } private void WReceived(WChannel channel, byte[] data) { long sessionId = channel.SessionId; if (sessionDic.TryGetValue(sessionId, out Session session)) { //因为没去掉头 Received(session,data,0); } else { Debug.Error("接收到webSocket包,未找到会话!"); } } private void WError(WChannel channel, Exception e) { Debug.Error("Web Socket Error:" + e.Message); } #endregion /// /// 接受到数据 /// /// /// /// private void Received(Session session, byte[] data,int offset) { try { //opcode int opcode = BitConverter.ToInt32(data, offset); offset += 4; //4个备份字节 offset += 4; //后面是包内容 //Debug.Info($"接收到数据{opcode},{data.Length}"); Type messageType = MessageManager.GetType(opcode); MessageData messageData = (MessageData)MessagePackSerializer.Deserialize(messageType, new ReadOnlyMemory(data, offset, data.Length - offset)); MessageDispatcher.Instance.AddPack(GamePacket.Create(opcode, messageData, session)); Interlocked.Exchange(ref session.ReadWriteTime, TimeInfo.Instance.FrameTime); Interlocked.Add(ref ReceiveCount, 1); } catch (Exception e) { Debug.Error($"收包解析报错:{e.Message}"); } } public void Update() { // 清理超时,和失效的链接 long timeNow = TimeInfo.Instance.FrameTime; const int MaxCheckNum = 10; int n = sessionIds.Count; if (n > MaxCheckNum) { n = MaxCheckNum; } for (int i = 0; i < n; i++) { if (this.sessionIds.TryDequeue(out long sessionId)) { if (this.sessionDic.TryGetValue(sessionId, out Session session)) { if (timeNow - session.ReadWriteTime > 20 * 1000) { Debug.Info($"超时断线! {session.IsDisConnected}"); //var key = Debug.StartTiming(); session.DisConnected(); // double runtime = Debug.GetRunTime(key); // if (runtime > 20) // { // Debug.Warning($"NetManager runtime:{runtime},n:{n}"); // } //超时断线 continue; } this.sessionIds.Enqueue(sessionId); } } else { break; } } } } }