Light12306/ChatRoomServer.Main/ChatServer.cs
2015-07-15 20:55:09 +08:00

224 lines
5.5 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://127.0.0.1/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);
}
}
}
private void ChatServer_NewSessionConnected(ChatSession session)
{
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);
}
}
}