using Prism.Mvvm; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; using OnlineUserPool.Hander; using OnlineUserPool.Model; using OnlineUserPool.Unility; using Serilog; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using System.Windows.Threading; using System.Diagnostics; using OnlineUserPool.Services; using Newtonsoft.Json; using System.Collections.Concurrent; using System.IO.Compression; using System.IO; using System.Windows; using OnlineUserPool.Api; using OnlineUserPool.Api.Model; namespace OnlineUserPool.ViewModels { public class MainWindowViewModel : BindableBase { public ObservableCollection Clients { get; private set; } = new ObservableCollection(); private static ConcurrentBag receiveMes = new ConcurrentBag(); private static CustomList RoomList = new CustomList(); private static int RoomMaxId = 0; private static int Ticks = 0; private static object locker = new object(); public static System.Timers.Timer timer; private static IHandle mapRecordRankingHander; private Dispatcher dispatcher; public ObservableCollection Customers { get; private set; } = new ObservableCollection(); private string _Title = ""; public string Title { get { return _Title; } set { SetProperty(ref _Title, value); } } private string _SendDataSize = ""; public string SendDataSize { get { return _SendDataSize; } set { SetProperty(ref _SendDataSize, value); } } private string _VirtualData = ""; public string VirtualData { get { return _VirtualData; } set { SetProperty(ref _VirtualData, value); } } private bool _closeVirtualUser = false; public bool CloseVirtualUser { get { return _closeVirtualUser; } set { SetProperty(ref _closeVirtualUser, value); } } //private IService _udpService; public MainWindowViewModel() { //初始化对战房间信息 var r = GameRoomHelper.Get(); foreach (var item in r) { RoomList.Add(item); } RoomMaxId = GameRoomHelper.GetMaxId(); //初测程序关闭事件 Application.Current.MainWindow.Closing += MainWindow_Closing; Title = $"{ IPAddress.Any }:{ ConfigHelp.UdpPort }"; dispatcher = Dispatcher.CurrentDispatcher; //Customers.Add("suntao"); WriteLine(DateTime.Now.ToShortDateString()); LogHelper.Init(); mapRecordRankingHander = new MapRecordRankingHander();// //mapRecordRankingHander = new MultiUserHandle(); Log.Information($"初始化连接,当前地址:{ IPAddress.Any }:{ConfigHelp.UdpPort}"); new TcpService1().RunServer(ReceivedData, CientDisconnected); //var tet = new System.Collections.Concurrent.ConcurrentBag(); var _udpService = new UdpService(); _udpService.RunServer(ReceivedData); Log.Information("服务启动成功"); timer = new System.Timers.Timer(500); timer.Elapsed += Timer_Elapsed; timer.AutoReset = true; timer.Start(); Log.Information("等待连接"); //Console.ReadKey(); } private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { GameRoomHelper.Set(RoomList.ToList()); GameRoomHelper.SetMaxId(RoomMaxId); } private void ReceivedData(IPEndPoint remoteIpEndPoint, ReceiveModel msg, IService service) { dispatcher.Invoke(() => { if (!Clients.Any(c => c.Equals(remoteIpEndPoint))) { Clients.Add(new HostModel { IPEndPoint = remoteIpEndPoint, LastActiveTime = DateTime.Now, //RouteId = msg.RouteId, //MemberId = msg.MemberId, //V = msg.V, //Encoding = msg.Encoding, //Client = msg.Client, Service = service }); } switch (msg.CommandType) { //ping命令 case 0: { var client = Clients.FirstOrDefault(n => n.Equals(remoteIpEndPoint)); client.LastActiveTime = DateTime.Now; if (msg.V > 0) { client.V = msg.V; } } break; //消息 case 1: { var client = Clients.FirstOrDefault(n => n.Equals(remoteIpEndPoint)); var msg1 = (msg as MsgModel); client.Competitionid = msg1.Competitionid; client.Model = msg1.Model; if (client.Model == "") { client.RoomId = msg1.RoomId; } if (msg1.V > 0) { client.V = msg1.V; } receiveMes.Add(msg1); HandleGameRoomSaved(msg1); } break; //设置客户端 case 2: { var client = Clients.FirstOrDefault(n => n.Equals(remoteIpEndPoint)); var msg1 = (msg as SetClientCommand); client.Encoding = msg1.Encoding; client.Client = msg1.Client; client.V = msg1.V; client.MemberId = msg1.MemberId; client.Competitionid = msg1.Competitionid; client.IsWatch = msg1.IsWatch; } break; //GameRoom case 3: { HandleGameRoom(msg); } break; default: break; } if (msg.CommandType == 0) { //client.ShowVirtual = msg.ShowVirtual; } else if (msg.CommandType == 1) { } }); } private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { Ticks++; NotifyClient(); //定时保存当前房间信息 if (Ticks % 5 == 0) { GameRoomHelper.SetMaxId(RoomMaxId); GameRoomHelper.Set(RoomList.ToList()); } } private void HandleGameRoomSaved(MsgModel msg1) { //对战房间内的人保存处理 if (msg1.RoomId > 0 && msg1.Saved) { var current = RoomList.ToList().Where(c => c.RoomId == msg1.RoomId).FirstOrDefault(); if (current != null) { //更新房间内的人的保存状态 var currentPlayer = current.List.Where(c => c.UserId == msg1.MemberId).FirstOrDefault(); if (currentPlayer != null) { currentPlayer.Saved = true; } var notAllSaved = current.List.Where(c => !c.Saved).Any(); if (!notAllSaved && current.Status != 2) { current.Status = 2; WebService.UpdateGameRoom(current.RoomId, current.Status); } if (!current.Saved) { notAllSaved = current.List.Where(c => !c.Saved).Any(); if (!notAllSaved && current.Status != 2) { current.Status = 2; } current.Saved = true; WebService.AddGameRoom(current.RoomId, current.Status, current.UserId, current.Name, current.MapRouteId, current.Password, current.StartTime.Value, current.CloseTime, current.MaxMembers); } } } } private void HandleGameRoom(ReceiveModel msg) { //收 switch (msg.SubType) { case 0: HandleCreateGameRoom(msg); break; case 1: HandleJoinGameRoom(msg); break; case 2: HandleGameRoomReadyStatus(msg); break; case 3: HandleGameRoomStart(msg); break; case 4: HandleGameRoomKick(msg); break; case 5: HandleGameRoomProcess(msg); break; case 6: HandleQueryGameRoomList(msg); break;//查询房间列表 default: break; } switch (msg.SubType) { case 0: case 1: case 2: case 3: case 4: BroadCastGameRoomList(); break; } } private void SendGameRoomMessage(RoomModel gameRoom) { if (gameRoom == null) return; var list = new List(); list.Add(new MsgModel() { V = 2, Point = new double[] { 0d, 0d }, }); string ss = ""; if (gameRoom.List != null && gameRoom.List.Count > 0) { ss = string.Join("|", gameRoom.List.Select(c => c.ToString())); } int total = 0; var G = $"{total}l[{gameRoom},detail{{{ss}}}]"; var temp = string.Join("|", list.Select(m => m.ToString(2))) + "|"; var strV21 = $"*l{{{ temp }}};g{{{ G}}};#"; var ddd = new Data1(strV21); var needList = Clients.Where(c => c.RoomId == gameRoom.RoomId).ToList(); foreach (var client in needList) { bool isZip = client.Encoding == "gzip"; client.Service.Send(ddd.GetBytes(isZip), ddd.GetBytes(isZip).Length, client.IPEndPoint); client.Request = ""; } } private void BroadCastGameRoomList() { //广播 var needlist = Clients.Where(c => c.Model != null && c.Model.Equals("GameRoom") && !string.IsNullOrEmpty(c.Request)); var list = new List(); list.Add(new MsgModel() { V = 2, Point = new double[] { 0d, 0d }, }); var temp = string.Join("|", list.Select(m => m.ToString(2))) + "|"; foreach (var item in needlist) { var G = GameRoomMessageHandler(item); var strV21 = $"*l{{{ temp }}};g{{{G}}};#"; var ddd = new Data1(strV21); bool isZip = item.Encoding == "gzip"; item.Service.Send(ddd.GetBytes(isZip), ddd.GetBytes(isZip).Length, item.IPEndPoint); } } //查询房间列表 private void HandleQueryGameRoomList(ReceiveModel msg) { var query = msg as QueryGameRoomListCommand; var needSend = Clients.Where(c => c.MemberId == query.UserId).FirstOrDefault(); if (needSend == null) return; needSend.Request = $"List/{query.PageIndex}/{query.PageSize}/{query.Name}"; var list = new List(); list.Add(new MsgModel() { V = 2, Point = new double[] { 0d, 0d }, }); var temp = string.Join("|", list.Where(m => m.Competitionid == needSend.Competitionid).Select(m => m.ToString(2))) + "|"; List rooms; if (!string.IsNullOrEmpty(query.Name)) { rooms = RoomList.ToList().Where(c => c.Name.Contains(query.Name) || c.RoomId.ToString() == query.Name).OrderBy(c => c.Status).ThenByDescending(c => c.CreateTime).ToList(); } else { rooms = RoomList.ToList().OrderBy(c => c.Status).ThenByDescending(c => c.CreateTime).ToList(); } //计算总页数 int total = 0; if (query.PageSize != 0) { total = rooms.Count() / query.PageSize; total = rooms.Count() % query.PageSize == 0 ? total : total + 1; } rooms = rooms.Skip(query.PageIndex * query.PageSize).Take(query.PageSize).ToList(); string roomInfo = $"{total}l"; foreach (var r in rooms) { string ss = ""; if (r.List != null && r.List.Count > 0) { ss = string.Join("|", r.List.Select(c => c.ToString())); } roomInfo += $"[{r.ToString()},detail{{{ss}}}]"; } var strV21 = $"*l{{{ temp }}};g{{{roomInfo}}};#"; var ddd = new Data1(strV21); bool isZip = needSend.Encoding == "gzip"; needSend.Service.Send(ddd.GetBytes(isZip), ddd.GetBytes(isZip).Length, needSend.IPEndPoint); } //创建房间 private void HandleCreateGameRoom(ReceiveModel msg) { var createMsg = msg as CreateGameRoomCommand; RemoveOtherRoomInfo(createMsg.UserId, createMsg.Id); var roomId = RoomMaxId + 1; var list = new List(); list.Add(new RoomDetailModel() { RoomId = roomId, UserId = createMsg.UserId, JoinAt = DateTime.Now.ToUniversalTime(), IsOwner = true, }); var room = new RoomModel { RoomId = roomId, Name = createMsg.Name, Password = createMsg.Password, CloseTime = createMsg.CloseTime, CreateTime = createMsg.CreateTime, MapRouteId = createMsg.RouteId, MapRouteName = createMsg.MapRouteName, AltitudeGraph = createMsg.AltitudeGraph, MaxMembers = createMsg.MaxMembers, UserId = createMsg.UserId, AverageGrade = createMsg.AverageGrade, TotalClimb = createMsg.TotalClimb, Distance = createMsg.Distance, EnableAR = createMsg.EnableAR, Enable3D = createMsg.Enable3D, FileName = createMsg.FileName, FileUrl = createMsg.FileUrl, IsLock = !string.IsNullOrEmpty(createMsg.Password), List = list, }; var mine = Clients.Where(c => c.MemberId == createMsg.UserId).FirstOrDefault(); if (mine != null) { mine.RoomId = room.RoomId; } RoomList.Add(room); RoomMaxId = room.RoomId; } //先移除当前用户在其他房间的信息(考虑服务器重启的时候没有响应客户端退出命令) private void RemoveOtherRoomInfo(int userId, int roomId) { var preRoom = RoomList.ToList().FirstOrDefault(c => c.Status == 0 && c.List.Any(a => a.UserId == userId) && c.RoomId != roomId); if (preRoom != null) { var needRemove = preRoom.List.FirstOrDefault(c => c.UserId == userId && c.Saved == false); preRoom.List.Remove(needRemove); if (preRoom.List.Count == 0) { RoomList.Remove(preRoom); } //发送给这个房间的人 SendGameRoomMessage(preRoom); } } //处理当前用户加入房间 private void HandleJoinGameRoom(ReceiveModel msg) { var msg1 = msg as JoinGameRoomCommand; RemoveOtherRoomInfo(msg1.UserId,msg1.RoomId); var room = RoomList.ToList().Where(c => c.RoomId == msg1.RoomId).FirstOrDefault(); var client = Clients.FirstOrDefault(n => n.MemberId.Equals(msg1.UserId)); //更新房间信息 if (room != null) { var list = room.List; var member = list.Where(c => c.UserId == msg1.UserId).FirstOrDefault(); if (member != null) { member.JoinAt = msg1.JoinAt; } else { //如果房间人数已经满了就拒绝加入 var currentCount = room.List.Count; if (currentCount + 1 <= room.MaxMembers) { list.Add(new RoomDetailModel { UserId = msg1.UserId, JoinAt = msg1.JoinAt, RoomId = msg1.RoomId }); if (client != null) { client.RoomId = room.RoomId; client.Request = ""; } } } } //发送当前房间的信息给当前房间内的人 SendGameRoomMessage(room); } //处理当前用户准备状态 private void HandleGameRoomReadyStatus(ReceiveModel msg) { var msg1 = msg as GameRoomReadyCommand; var room = RoomList.ToList().Where(c => c.RoomId == msg1.RoomId).FirstOrDefault(); if (room != null) { var list = room.List; var member = list.Where(c => c.UserId == msg1.UserId).FirstOrDefault(); if (member != null) { member.Status = msg1.Status; } } //发送信息给当前房间内的人 SendGameRoomMessage(room); } //处理当前用户准备状态 private void HandleGameRoomStart(ReceiveModel msg) { var msg1 = msg as GameRoomStartCommand; var client = Clients.Where(c => c.MemberId == msg1.UserId).FirstOrDefault(); if (client != null) { client.RoomId = msg1.RoomId; } var room = RoomList.ToList().Where(c => c.RoomId == msg1.RoomId).FirstOrDefault(); if (room != null) { room.Status = 1; room.StatusChangedTime = DateTime.Now; } //发送信息给当前房间内的人 SendGameRoomMessage(room); } //处理房间踢人的操作 private void HandleGameRoomKick(ReceiveModel msg) { var msg1 = msg as GameRoomKickCommand; var room = RoomList.ToList().FirstOrDefault(c => c.RoomId == msg1.RoomId); if (room != null) { var list = room.List; var needRemove = list.FirstOrDefault(c => c.UserId == msg1.UserId); if (needRemove != null) { list.Remove(needRemove); //如果当前是房主退出房间,房主替换成其他人, 房主客户端中断也算 if (needRemove.IsOwner && list.Any()) { var newOwner = list.FirstOrDefault(); newOwner.IsOwner = true; room.UserId = newOwner.UserId; } } //房间没有产生记录且人数为0,删除房间 if (!room.Saved && !list.Any()) { RoomList.Remove(room); } var mine = Clients.FirstOrDefault(c => c.MemberId == msg1.UserId); if (mine != null) { mine.RoomId = 0; } //发送信息给当前房间内的人 SendGameRoomMessage(room); } } private const int ROOM_TIME_OUT = 60; private const int TOTAL_PROCESS = 100; //处理房间内人loading进度 private void HandleGameRoomProcess(ReceiveModel msg) { var msg1 = msg as GameRoomProcessCommand; var room = RoomList.ToList().Where(c => c.RoomId == msg1.RoomId).FirstOrDefault(); var client = Clients.Where(c => c.MemberId == msg1.UserId).FirstOrDefault(); if (room != null) { var list = room.List; var player = list.Where(c => c.UserId == msg1.UserId).FirstOrDefault(); if (player != null) { player.Process = msg1.Process; } var notReady = list.Where(c => c.Process < TOTAL_PROCESS).Any(); var now = DateTime.Now; var timespan = now - room.StatusChangedTime; //超时时间1分钟所有人强制开始 if ((notReady && timespan.TotalSeconds > ROOM_TIME_OUT) || !notReady) { room.StartTime = now.AddSeconds(10).ToUniversalTime(); } if (client != null) { client.RoomId = room.RoomId; } SendGameRoomMessage(room); } } private string GameRoomMessageHandler(HostModel item) { //如果当前Client有请求房间列表信息,发送房间列表信息 var G = ""; if (!string.IsNullOrEmpty(item.Request)) { var param = item.Request.Split('/'); var pageInfo = param[0]; if (pageInfo.Equals("List")) { var pageIndex = Convert.ToInt32(param[1]); var pageSize = Convert.ToInt32(param[2]); var querName = param[3].ToString(); List rooms; if (!string.IsNullOrEmpty(querName)) { rooms = RoomList.ToList().Where(c => c.Name.Contains(querName) || c.RoomId.ToString() == querName).OrderBy(c => c.Status).ThenByDescending(c => c.CreateTime).ToList(); } else { rooms = RoomList.ToList().OrderBy(c => c.Status).ThenByDescending(c => c.CreateTime).ToList(); } //计算总页数 int total = 0; if (pageSize != 0) { total = rooms.Count() / pageSize; total = rooms.Count() % pageSize == 0 ? total : total + 1; } G = $"{total}l"; rooms = rooms.Skip(pageIndex * pageSize).Take(pageSize).ToList(); foreach (var r in rooms) { string ss = ""; if (r.List != null && r.List.Count > 0) { ss = string.Join("|", r.List.Select(c => c.ToString())); } G += $"[{r.ToString()},detail{{{ss}}}]"; } } } return G; } private void NotifyClient() { try { if (!receiveMes.Any()) { dispatcher.Invoke(() => { //Customers.Clear(); //删除已经发送的数据 //receiveMes.Clear(); //移除5钟内连接不上的客户端 Clients.ToList().ForEach(item => { if (item.Expire) { RemoveClient(item); } }); }); return; } lock (locker) { var msgs = CloneJson(receiveMes).ToList(); receiveMes.Clear(); if (!CloseVirtualUser) { //加入虚拟人物消息 var virtualData = mapRecordRankingHander.GetVirtualUserData(); VirtualData = $"{virtualData.Count}"; WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-当前在线人数:" + Clients.Count + "-当前虚拟人数:" + virtualData.Count); #if DEBUG WriteLine($"在线人:{Newtonsoft.Json.JsonConvert.SerializeObject(msgs)}"); //\r\n虚拟人:{Newtonsoft.Json.JsonConvert.SerializeObject(virtualData)} #endif msgs.AddRange(virtualData); } //屏蔽房间模式的用户 var c = Clients.Where(c => string.IsNullOrEmpty(c.Model)).ToList(); SendMessage(c, msgs); dispatcher.Invoke(() => { Customers.Clear(); foreach (var item in msgs) { if (Customers.Any(c => c.MemberId == item.MemberId)) { continue; } Customers.Add(item); } //移除下线的客户端 for (int i = 0; i < msgs.Count; i++) { if (msgs[i].exit && msgs[i].MemberId > 0)//客户端退出,并且不是虚拟的人物 { //这个地方有严重的逻辑错误(虚拟的人物不能和真实的人用同一个名字) var info = Clients.FirstOrDefault(n => n.MemberId == msgs[i].MemberId); if (info != null) { RemoveClient(info); } } } //删除已经发送的数据 //receiveMes.Clear(); //移除5钟内连接不上的客户端 Clients.ToList().ForEach(item => { if (item.Expire) { RemoveClient(item); } }); }); } //更新虚拟人物信息 mapRecordRankingHander.RemoveEndAndAddNewVirtualUser(Customers.Count); } catch (Exception e) { Log.Error($"NotifyClient:{ e.Message }\r\n{ e.StackTrace }"); } } private void SendMessage(IList clients, List msgModels) { if (!clients.Any() || !msgModels.Any()) { return; } var clients1 = clients.ToList(); var list = CloneJson>(msgModels); foreach (var item in list) { item.PreDistance = Math.Round(item.PreDistance, 5); item.EndDistance = Math.Round(item.EndDistance, 5); item.WeightKg = Math.Round(item.WeightKg, 2); } string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(list.Select(m => new { m.RouteId, m.MemberId, m.Point, m.IsCompleted, m.exit, m.Speed, m.PreDistance, m.EndDistance, //m.IsVirtual,//后面要把这个字段过滤掉 m.WeightKg, m.Competitionid, m.Saved, m.FrameRate, })); var data = Encoding.ASCII.GetBytes(jsonString); //SendDataSize = (data.Length/1000D).ToString() +"KB"; var strV1 = string.Join("|", list.Select(m => m.ToString(1))); if (!string.IsNullOrWhiteSpace(strV1)) { strV1 += "|"; } //strV1 = "abcdefghijklmnopqrstuvwxyz"; //System.IO.File.AppendAllText(System.Environment.CurrentDirectory + "要发送的数据.txt", strV1.Trim().Replace("\0", "") + "\r\n", Encoding.UTF8); WriteLine(strV1); WriteLine(strV1.Length.ToString()); //var dataV1 = Encoding.UTF8.GetBytes(strV1); //var dataV1ForUdp = strV1.Last() == '|' ? Encoding.ASCII.GetBytes(strV1.Substring(0, strV1.Length - 1)) : dataV1; //var dataCompressV1 = Encoding.UTF8.GetBytes($"*{ Convert.ToBase64String(CommonHelper.Compress(strV1)) }#"); var data1 = new Data1(strV1); var data1ForUdp = new Data1(strV1.Last() == '|' ? strV1.Substring(0, strV1.Length - 1) : strV1); //var watchList = string.Join('|', clients1.Where(c => c.IsWatch).Select(c => c.MemberId)); //var strV2 = $"*l{{{ strV1 }}};w{{{ watchList }}}#"; ////var dataCompressV2 = Encoding.UTF8.GetBytes($"{ Convert.ToBase64String(CommonHelper.Compress(strV2)) }"); //var data2 = new Data1(strV2); SendDataSize = $"\t单客户端数据包V1:{ data1.GetBytes().Length / 1000D }KB,一共占用带宽:{ data1.GetBytes().Length / 1000D * clients1.Count }KB,压缩以后{ data1.GetBytes(true).Length / 1000D * clients1.Count }KB"; #region 发送数据 foreach (var item in clients1) { try { if (item == null) { continue; } //if((item.Service is UdpService) ==false) //{ // continue; //} if (item.V != 1 && item.V != 2) { item.Service.Send(data, data.Length, item.IPEndPoint); continue; } if (item.V == 1 && item.Service is UdpService) { item.Service.Send(data1ForUdp.GetBytes(), data1ForUdp.GetBytes().Length, item.IPEndPoint); } else { Data1 ddd = null;// = item.V == 1 ? ; if (item.V == 1) { ddd = data1; } else if (item.V == 2) { var temp = string.Join("|", list.Where(m => m.Competitionid == item.Competitionid).Select(m => m.ToString(2))) + "|"; var watchList1 = string.Join('|', clients1.Where(c => c.IsWatch && c.Competitionid == item.Competitionid).Select(c => c.MemberId)); var e = string.Join("|", list.Where(c => c.RoomId > 0 || c.FrameRate > 0).Select(c => $"{c.MemberId},{c.RoomId},{c.FrameRate},{c.TotalTicks}")); var strV21 = $"*l{{{ temp }}};w{{{ watchList1 }}};e{{{ e }}};#"; ddd = new Data1(strV21); } else { continue; } bool isZip = item.Encoding == "gzip"; item.Service.Send(ddd.GetBytes(isZip), ddd.GetBytes(isZip).Length, item.IPEndPoint); } } catch (Exception e) { Debug.WriteLine(e.Message); Log.Error($"{ item.IPEndPoint.ToString() }:{ e.Message }\r\n{ e.StackTrace }"); } } #endregion } private void GameRoomDisConnectHandler(HostModel client) { ////如果是在对战房间或者对战列表掉线执行,骑行阶段断开连接不移除房间信息 //if (client.Model != null && !client.Model.Equals("GameRoom")) // return; RoomList.ToList().ForEach(o => { if (o.List != null && o.Status != 2) { var needRemove = o.List.FirstOrDefault(c => c.UserId == client.MemberId && c.Saved == false); o.List.Remove(needRemove); } }); var needRemoveList = RoomList.ToList().Where(c => c.List.Count == 0 && c.Status != 2).ToList(); foreach (var item in needRemoveList) { RoomList.Remove(item); } BroadCastGameRoomList(); } void WriteLine(string str) { //Debug.WriteLine(str); } T CloneJson(T source) { // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } // initialize inner objects individually // for example in default constructor some list property initialized with some values, // but in 'source' these items are cleaned - // without ObjectCreationHandling.Replace default constructor values will be added to result var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace }; return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source), deserializeSettings); } private void CientDisconnected(EndPoint point) { dispatcher.Invoke(() => { try { var client = Clients.FirstOrDefault(f => f.IPEndPoint.ToString() == point.ToString()); if (client != null) { RemoveClient(client); GameRoomDisConnectHandler(client); } } catch(Exception ex) { Log.Information("在CientDisconnected触发以后,删除client时报错了,"+ ex.Message +", " + ex.StackTrace); } }); } private void RemoveClient(HostModel client) { BeforeRemoved(client); Clients.Remove(client); } private void BeforeRemoved(HostModel client) { if(client.RoomId == 0)return; var room = RoomList.ToList().FirstOrDefault(c => c.RoomId == client.RoomId); if(room == null)return; var needRemove = room.List.FirstOrDefault(c => c.UserId == client.MemberId && c.Saved == false); if(needRemove == null)return; //从房间中移除,并考虑是否需要删除房间和移交房主 room.List.Remove(needRemove); if (room.List.Count == 0) { RoomList.Remove(room); } else { var host = room.List.FirstOrDefault(); if (host != null) { host.IsOwner = true; } } //更新房间状态 var isComplete = room.List.All(c => c.Saved != false); if (room.Status > 0) { room.Status = isComplete ? 2 : 1; } } } public class Data1 { private string _txt = ""; public Data1(string txt) { this._txt = txt; } public byte[] GetBytes(bool compress = false) { if (compress) { return GetCompressBytes(); } return Encoding.UTF8.GetBytes(this._txt); } private byte[] GetCompressBytes() { var temp = this._txt; if(temp[0] == '*') { temp = temp.Substring(1); } if(temp.Last() == '#') { temp = temp.Substring(0, temp.Length - 1); } return Encoding.UTF8.GetBytes($"*{ Convert.ToBase64String(CommonHelper.Compress(temp)) }#"); } } }