232 lines
5.8 KiB
C#
232 lines
5.8 KiB
C#
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<ChatSession>
|
|
{
|
|
static ILog _log;
|
|
static readonly object _lockObject = new object();
|
|
internal static HashSet<string> 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<ChatSession, RoomContainer> _containers = new ConcurrentDictionary<ChatSession, RoomContainer>();
|
|
ConcurrentDictionary<string, RoomContainer> _roomContainers = new ConcurrentDictionary<string, RoomContainer>();
|
|
|
|
#region block users
|
|
|
|
Timer _blockUserReloadTimer;
|
|
Dictionary<string, DateTime?> _blockUsers = new Dictionary<string, DateTime?>(StringComparer.OrdinalIgnoreCase);
|
|
readonly object _blockUserLockObject = new object();
|
|
|
|
public Dictionary<string, DateTime?> BlockUsers
|
|
{
|
|
get { return _blockUsers; }
|
|
}
|
|
|
|
void ReloadBlockUsers()
|
|
{
|
|
var db = new ChatDb();
|
|
var blockUsers = db.Database.SqlQuery<BlockUser>("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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when [started].
|
|
/// </summary>
|
|
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<string>(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.CreatePost<string>("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);
|
|
}
|
|
}
|
|
}
|