using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ChatRoomServer.Main { using System.Collections.Concurrent; using System.Net; using System.Timers; using ChatRoomServer.Db; using ChatRoomServer.Db.Entities; using ChatRoomServer.Main.Room; using FSLib.Logs.Log4Net; using FSLib.Network.Http; using FSLib.Network.SuperSocket.Protocols.WebSocket; using FSLib.Network.SuperSocket.SocketBase; using Newtonsoft.Json; class ChatServer : WebSocketServer { static ILog _log; static readonly object _lockObject = new object(); internal static HashSet PresetAdministrators = (System.Configuration.ConfigurationManager.AppSettings["chat:admin"] ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToHashSet(StringComparer.OrdinalIgnoreCase); static ChatServer() { FSLib.Logs.Log4NetBootStraper.Initialize("log4net.server.config", "Server"); _log = GetLogger(typeof(ChatServer).Name); } ConcurrentDictionary _containers = new ConcurrentDictionary(); ConcurrentDictionary _roomContainers = new ConcurrentDictionary(); #region block users Timer _blockUserReloadTimer; Dictionary _blockUsers = new Dictionary(StringComparer.OrdinalIgnoreCase); readonly object _blockUserLockObject = new object(); public Dictionary BlockUsers { get { return _blockUsers; } } void ReloadBlockUsers() { var db = new ChatDb(); var blockUsers = db.Database.SqlQuery("exec usp_BlockUser_GetList").ToArray(); lock (_blockUserLockObject) { _blockUsers.Clear(); blockUsers.ForEach(s => { if (!_blockUsers.ContainsKey(s.UserName)) _blockUsers.Add(s.UserName, s.UnblockTime); else { var item = _blockUsers[s.UserName]; if (item != null && (s.UnblockTime == null || s.UnblockTime > item.Value)) { _blockUsers[s.UserName] = s.UnblockTime; } } }); } _log.Info("已刷新屏蔽列表。"); //处理连接 GetAllSessions().ForEach(s => { if (_blockUsers.ContainsKey(s.UserName)) s.Block(_blockUsers[s.UserName]); }); } public void AddBlockUser(string username, DateTime? unblockTime) { lock (_blockUserLockObject) { if (!_blockUsers.ContainsKey(username)) _blockUsers.Add(username, unblockTime); else { var item = _blockUsers[username]; if (item != null && (unblockTime == null || unblockTime > item.Value)) { _blockUsers[username] = unblockTime; } } } } #endregion internal static ILog GetLogger(string name) { return LogManager.GetLogger("Server", name); } /// /// Called when [started]. /// protected override void OnStarted() { base.OnStarted(); NewSessionConnected += ChatServer_NewSessionConnected; NewDataReceived += ChatServer_NewDataReceived; SessionClosed += ChatServer_SessionClosed; InitOnlineCountSync(); //黑名单 _blockUserReloadTimer = new Timer(1000 * 60 * 1) { AutoReset = false }; _blockUserReloadTimer.Elapsed += (s, e) => { try { ReloadBlockUsers(); } catch (Exception) { } _blockUserReloadTimer.Start(); }; ReloadBlockUsers(); _blockUserReloadTimer.Start(); } #region 在线人数上报 System.Timers.Timer _syncOnlineCountTimer; void InitOnlineCountSync() { _syncOnlineCountTimer = new Timer(60 * 1000); _syncOnlineCountTimer.AutoReset = false; _syncOnlineCountTimer.Elapsed += (s, e) => { UploadOnlineCount(); _syncOnlineCountTimer.Start(); }; UploadOnlineCount(); _syncOnlineCountTimer.Start(); } void UploadOnlineCount() { var datas = _roomContainers.ToArray(); var data = datas.Select(s => new { id = s.Key, count = s.Value.SessionCount }).ToArray(); var client = new HttpClient(); string url; #if DEBUG url = "http://chatdev.fishlee.net/api/room/updateOnlineCount"; #else url = "http://srv.12306.liebao.cn/api/room/updateOnlineCount"; #endif var ctx = client.Create(HttpMethod.Post, url, data: data, payloadType: RequestPayloadType.Json).Send(); if (ctx.IsValid()) { _log.Info("同步房间在线人数成功。"); } else { _log.InfoFormat("同步房间在线人数失败。错误信息:" + (ctx.Exception?.Message ?? "") + ",状态码:" + (ctx.Status ?? HttpStatusCode.Unused)); } } #endregion private void ChatServer_SessionClosed(ChatSession session, CloseReason value) { RoomContainer roomContainer; if (_containers.TryRemove(session, out roomContainer)) { roomContainer.Remove(session); if (roomContainer.SessionCount == 0) { _roomContainers.TryRemove(roomContainer.Id, out roomContainer); //upload zero count var data = new object[] { new { id = roomContainer.Id, count = 0 } }; var client = new HttpClient(); client.Post("http://srv.12306.liebao.cn/api/room/updateOnlineCount", data, usingJsonBody: true).Send(); } } } private void ChatServer_NewSessionConnected(ChatSession session) { if (session.IsSessionBlocked) return; var cmd = session.Command; if (cmd == "room" && session.PathSegements.Length >= 4) { var roomid = session.Id; //TODO check roomid var roomCtx = _roomContainers.GetOrAdd(roomid, _ => new RoomContainer(_)); _containers.AddOrUpdate(session, roomCtx); roomCtx.Add(session); //send online count } else { session.Close(CloseReason.ProtocolError); } } private void ChatServer_NewDataReceived(ChatSession session, byte[] value) { session.ProcessData(value); } } }