From 23db5358fb5f7d00c5563dd7a2339004da32d3a9 Mon Sep 17 00:00:00 2001 From: sin365 <353374337@qq.com> Date: Fri, 20 Sep 2024 18:27:13 +0800 Subject: [PATCH] room mgr fix --- AxibugEmuOnline.Server/Common/Config.cs | 74 ++++++++ .../Common/Haoyue_SQLPoolManager.cs | 178 ++++++++++++++++++ AxibugEmuOnline.Server/Common/Helper.cs | 20 +- AxibugEmuOnline.Server/Manager/AppSrv.cs | 5 +- AxibugEmuOnline.Server/Manager/RoomManager.cs | 11 +- AxibugEmuOnline.Server/Program.cs | 67 ++++++- 6 files changed, 351 insertions(+), 4 deletions(-) create mode 100644 AxibugEmuOnline.Server/Common/Config.cs create mode 100644 AxibugEmuOnline.Server/Common/Haoyue_SQLPoolManager.cs diff --git a/AxibugEmuOnline.Server/Common/Config.cs b/AxibugEmuOnline.Server/Common/Config.cs new file mode 100644 index 0000000..86c0834 --- /dev/null +++ b/AxibugEmuOnline.Server/Common/Config.cs @@ -0,0 +1,74 @@ +using System.Data; +using System.Text.Encodings.Web; +using System.Text; +using System.Text.Json; +using System.Text.Unicode; + +namespace AxibugEmuOnline.Server.Common +{ + + public class ConfigDataModel + { + public string DBIp{get;set;} + public ushort DBPort{get;set; } + public string DBName { get; set; } + public string DBUname{get;set;} + public string DBPwd{get;set;} + public string RomDir{get;set;} + public string ImageDir { get; set; } + public string ServerIp { get; set; } + public ushort ServerPort { get; set; } + public string ClientVersion { get; set; } + } + + + public static class Config + { + public static ConfigDataModel cfg; + public static bool LoadConfig() + { + try + { + string path = System.Environment.CurrentDirectory + "//config.cfg"; + if (!File.Exists(path)) + { + ConfigDataModel sampleCfg = new ConfigDataModel + { + DBIp = "127.0.0.1", + DBPort = 3306, + DBUname = "user", + DBPwd = "password", + DBName = "DBName", + RomDir = "./Rom", + ImageDir = "./Img", + ServerIp = "127.0.0.1", + ServerPort = 10001, + ClientVersion = "0.0.0.1" + }; + + string jsonString = JsonSerializer.Serialize(sampleCfg, new JsonSerializerOptions() + { + // 整齐打印 + WriteIndented = true, + //重新编码,解决中文乱码问题 + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + }); + System.IO.File.WriteAllText(path, jsonString, Encoding.UTF8); + + Console.WriteLine("未找到配置,已生成模板,请浏览" + path); + return false; + } + StreamReader sr = new StreamReader(path, Encoding.Default); + String jsonstr = sr.ReadToEnd(); + cfg = JsonSerializer.Deserialize(jsonstr); + sr.Close(); + return true; + } + catch (Exception ex) + { + Console.WriteLine("配置文件异常:" + ex.ToString()); + return false; + } + } + } +} diff --git a/AxibugEmuOnline.Server/Common/Haoyue_SQLPoolManager.cs b/AxibugEmuOnline.Server/Common/Haoyue_SQLPoolManager.cs new file mode 100644 index 0000000..7138f47 --- /dev/null +++ b/AxibugEmuOnline.Server/Common/Haoyue_SQLPoolManager.cs @@ -0,0 +1,178 @@ +using MySql.Data.MySqlClient; + +namespace AxibugEmuOnline.Server.Common +{ + public static class Haoyue_SQLPoolManager + { + private static Queue SQLPool = new Queue(); + private static Dictionary _OutOfSQLPool = new Dictionary(); + private static Dictionary _DicSqlRunFunNum = new Dictionary(); + private static Dictionary _DicTimeOutSqlRunFunNum = new Dictionary(); + private const int DefaultCount = 1; + private const int MaxLimit = 5; + private static readonly object _sync = new object(); + + + private static MySqlConnectionStringBuilder connBuilder; + + public static void InitConnMgr() + { + connBuilder = new MySqlConnectionStringBuilder(); + connBuilder.Database = Config.cfg.DBName; + connBuilder.Server = Config.cfg.DBIp; + connBuilder.UserID = Config.cfg.DBUname; + connBuilder.Password = Config.cfg.DBPwd; + connBuilder.Port = Config.cfg.DBPort; + //connBuilder.MinimumPoolSize = 40u; + //connBuilder.MaximumPoolSize = 100u; + connBuilder.Pooling = true; + + + Console.WriteLine("SQLPool连接初始化...."); + for (int i = 0; i < DefaultCount; i++) + { + MySqlConnection _conn = conn(); + _conn.Open(); + SQLPool.Enqueue(_conn); + } + Console.WriteLine("SQLPool初始化完毕,连接数" + SQLPool.Count); + } + public static MySqlConnection conn() + { + return new MySqlConnection(connBuilder.ConnectionString); + } + + public static MySqlConnection DequeueSQLConn(string FuncStr) + { + lock (_sync) + { + if (_DicSqlRunFunNum.ContainsKey(FuncStr)) + { + _DicSqlRunFunNum[FuncStr]++; + } + else + { + _DicSqlRunFunNum[FuncStr] = 1L; + } + MySqlConnection _conn; + if (SQLPool.Count < 1) + { + Console.WriteLine("[DequeueSQLConn]创建新的SQLPool.Count>" + SQLPool.Count); + _conn = conn(); + _conn.Open(); + } + else + { + Console.WriteLine("[DequeueSQLConn]取出一个SQLCount.Count>" + SQLPool.Count); + _conn = SQLPool.Dequeue(); + } + _OutOfSQLPool.Add(_conn, new Haoyue_PoolTime + { + time = time(), + FuncStr = FuncStr + }); + return _conn; + } + } + public static void EnqueueSQLConn(MySqlConnection BackConn) + { + lock (_sync) + { + if (_OutOfSQLPool.ContainsKey(BackConn)) + { + _OutOfSQLPool.Remove(BackConn); + } + else + { + Console.WriteLine("出队遗漏的数据出现了!"); + } + if (SQLPool.Count > MaxLimit) + { + Console.WriteLine("已经不需要回收了,多余了,SQLPool.Count>" + SQLPool.Count); + BackConn.Close(); + BackConn = null; + } + else + { + SQLPool.Enqueue(BackConn); + Console.WriteLine("回收SQLPool.Count>" + SQLPool.Count); + } + } + } + + public static void CheckPoolTimeOut() + { + lock (_sync) + { + long now = time(); + List removeTemp = new List(); + foreach (KeyValuePair o2 in _OutOfSQLPool) + { + if (now - o2.Value.time >= 120) + { + if (_DicTimeOutSqlRunFunNum.ContainsKey(o2.Value.FuncStr)) + { + _DicTimeOutSqlRunFunNum[o2.Value.FuncStr]++; + } + else + { + _DicTimeOutSqlRunFunNum[o2.Value.FuncStr] = 1L; + } + if (SQLPool.Count > MaxLimit) + { + Console.WriteLine("[超时回收]" + o2.Value.FuncStr + "已经不需要回收了,多余了,SQLPool.Count>" + SQLPool.Count); + o2.Key.Close(); + } + else + { + Console.WriteLine("[超时回收]" + o2.Value.FuncStr + "回收SQLPool.Count>" + SQLPool.Count); + SQLPool.Enqueue(o2.Key); + } + removeTemp.Add(o2.Key); + } + } + if (removeTemp.Count() <= 0) + { + return; + } + foreach (MySqlConnection o in removeTemp) + { + if (_OutOfSQLPool.ContainsKey(o)) + { + _OutOfSQLPool.Remove(o); + Console.WriteLine("[超时回收]_OutOfSQLPool清理"); + } + else + { + Console.WriteLine("[超时回收]_OutOfSQLPool清理异常???????"); + } + } + Console.WriteLine("[超时回收]处理结束SQLPool.Count>" + SQLPool.Count); + } + } + public static long time() + { + return Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); + } + public static void GetPoolState() + { + Console.WriteLine("-----------------查询统计-----------------"); + foreach (KeyValuePair dic2 in _DicSqlRunFunNum) + { + Console.WriteLine(dic2.Key + ":" + dic2.Value); + } + Console.WriteLine("-----------------超时统计-----------------"); + foreach (KeyValuePair dic in _DicTimeOutSqlRunFunNum) + { + Console.WriteLine(dic.Key + ":" + dic.Value); + } + Console.WriteLine("------------------------------------------"); + } + } + + public class Haoyue_PoolTime + { + public long time { get; set; } + public string FuncStr { get; set; } + } +} diff --git a/AxibugEmuOnline.Server/Common/Helper.cs b/AxibugEmuOnline.Server/Common/Helper.cs index 9d5a278..a2a1463 100644 --- a/AxibugEmuOnline.Server/Common/Helper.cs +++ b/AxibugEmuOnline.Server/Common/Helper.cs @@ -1,4 +1,7 @@ -namespace AxibugEmuOnline.Server.Common +using System.Security.Cryptography; +using System.Text; + +namespace AxibugEmuOnline.Server.Common { public static class Helper { @@ -16,5 +19,20 @@ TimeSpan ts = dt - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds); } + + public static string FileMD5Hash(string filePath) + { + using (var md5 = MD5.Create()) + { + using (var stream = File.OpenRead(filePath)) + { + var hash = md5.ComputeHash(stream); + var sb = new StringBuilder(hash.Length * 2); + foreach (var b in hash) + sb.AppendFormat("{0:x2}", b); + return sb.ToString(); + } + } + } } } diff --git a/AxibugEmuOnline.Server/Manager/AppSrv.cs b/AxibugEmuOnline.Server/Manager/AppSrv.cs index 2d70a58..bfd0374 100644 --- a/AxibugEmuOnline.Server/Manager/AppSrv.cs +++ b/AxibugEmuOnline.Server/Manager/AppSrv.cs @@ -1,4 +1,5 @@ -using AxibugEmuOnline.Server.Manager; +using AxibugEmuOnline.Server.Common; +using AxibugEmuOnline.Server.Manager; using AxibugEmuOnline.Server.NetWork; using System.Net; @@ -17,6 +18,8 @@ namespace AxibugEmuOnline.Server public static void InitServer(int port) { + Config.LoadConfig(); + Haoyue_SQLPoolManager.InitConnMgr(); g_Tick = new TickManager(); g_ClientMgr = new ClientManager(); g_ClientMgr.Init(45000, 120); diff --git a/AxibugEmuOnline.Server/Manager/RoomManager.cs b/AxibugEmuOnline.Server/Manager/RoomManager.cs index cdcca5a..b15c886 100644 --- a/AxibugEmuOnline.Server/Manager/RoomManager.cs +++ b/AxibugEmuOnline.Server/Manager/RoomManager.cs @@ -224,10 +224,13 @@ namespace AxibugEmuOnline.Server if (joinErrcode == ErrorCode.ErrorOk && bHadRoomStateChange) SendRoomStateChange(room); + + + SendRoomUpdateToAll(room.RoomID, 0); } public void OnCmdRoomLeave(Socket sk, byte[] reqData) { - AppSrv.g_Log.Debug($"OnCmdRoomJoin "); + AppSrv.g_Log.Debug($"OnCmdRoomLeave "); ClientInfo _c = AppSrv.g_ClientMgr.GetClientForSocket(sk); Protobuf_Room_Leave msg = ProtoBufHelper.DeSerizlize(reqData); Protobuf_Room_Leave_RESP resp = new Protobuf_Room_Leave_RESP(); @@ -248,6 +251,12 @@ namespace AxibugEmuOnline.Server if (errcode == ErrorCode.ErrorOk && bHadRoomStateChange) SendRoomStateChange(room); + + SendRoomUpdateToAll(room.RoomID, 1); + if (room.GetPlayerCount() < 1) + RemoveRoom(room.RoomID); + + } public void OnHostPlayerUpdateStateRaw(Socket sk, byte[] reqData) diff --git a/AxibugEmuOnline.Server/Program.cs b/AxibugEmuOnline.Server/Program.cs index 09bd0d3..39fb88d 100644 --- a/AxibugEmuOnline.Server/Program.cs +++ b/AxibugEmuOnline.Server/Program.cs @@ -1,4 +1,6 @@ -using AxibugEmuOnline.Server.Manager; +using AxibugEmuOnline.Server.Common; +using AxibugEmuOnline.Server.Manager; +using MySql.Data.MySqlClient; namespace AxibugEmuOnline.Server { @@ -62,11 +64,74 @@ namespace AxibugEmuOnline.Server } } break; + case "updatehash": + { + UpdateRomHash(); + } + break; default: Console.WriteLine("未知命令" + CommandStr); break; } } } + + + static void UpdateRomHash() + { + AppSrv.g_Log.Info("UpdateRomHash"); + MySqlConnection conn = Haoyue_SQLPoolManager.DequeueSQLConn("UpdateRomHash"); + try + { + List<(int id, string romurl, string name)> list = new List<(int id, string romurl, string name)>(); + List<(int id, string romurl, string name)> Nonelist = new List<(int id, string romurl, string name)>(); + + string query = $"SELECT id,`Name`,GameType,Note,RomUrl,ImgUrl,`Hash` FROM romlist_nes"; + using (var command = new MySqlCommand(query, conn)) + { + // 执行查询并处理结果 + using (var reader = command.ExecuteReader()) + { + while (reader.Read()) + { + list.Add( + (reader.GetInt32(0), + !reader.IsDBNull(4) ? reader.GetString(4) : string.Empty, + !reader.IsDBNull(1) ? reader.GetString(1) : string.Empty + )); + } + } + } + + for (int i = 0; i < list.Count; i++) + { + string rompath = Config.cfg.RomDir + "/" + list[i].romurl; + rompath = System.Net.WebUtility.UrlDecode(rompath); + if (!File.Exists(rompath)) + { + Nonelist.Add(list[i]); + continue; + } + string romhash = Helper.FileMD5Hash(rompath); + AppSrv.g_Log.Info($"第{i}个,Name->{list[i].name},Hash->{romhash}"); + query = $"update romlist_nes SET `Hash` = '{romhash}' where Id ={list[i].id}"; + using (var command = new MySqlCommand(query, conn)) + { + // 执行查询并处理结果 + int reader = command.ExecuteNonQuery(); + if (reader > 0) + AppSrv.g_Log.Info($"第{i}个,处理成功"); + else + AppSrv.g_Log.Info($"第{i}个,处理失败"); + } + } + AppSrv.g_Log.Info($"处理完毕,共{Nonelist.Count}个文件没有找到"); + } + catch (Exception e) + { + AppSrv.g_Log.Info($"err:{e.ToString()}"); + } + Haoyue_SQLPoolManager.EnqueueSQLConn(conn); + } } } \ No newline at end of file