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; namespace OnlineUserPool.ViewModels { public class MainWindowViewModel : BindableBase { private static IPEndPoint serverIpEndPoint; private static UdpClient udpServer; public ObservableCollection Clients { get; private set; } = new ObservableCollection(); private static List receiveMes = new List(); private static object locker = new object(); public static System.Timers.Timer timer; private static MapRecordRankingHander 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); } } public MainWindowViewModel() { Title = $"{ ConfigHelp.Ip }:{ ConfigHelp.Port }"; dispatcher = Dispatcher.CurrentDispatcher; //Customers.Add("suntao"); WriteLine(DateTime.Now.ToShortDateString()); WriteLine("加载日志组件"); LogHelper.Init(); Log.Information("日志组件加载完成"); Log.Information("加载虚拟人物"); mapRecordRankingHander = new MapRecordRankingHander(); Log.Information("虚拟人物加载完成"); Log.Information($"初始化连接,当前地址:{ConfigHelp.Ip}:{ConfigHelp.Port}"); serverIpEndPoint = new IPEndPoint(IPAddress.Parse(ConfigHelp.Ip), ConfigHelp.Port); RunServer(); Log.Information("服务启动成功"); timer = new System.Timers.Timer(1000); timer.Elapsed += Timer_Elapsed; timer.AutoReset = true; timer.Start(); Log.Information("等待连接"); //Console.ReadKey(); } private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { NotifyClient(); } private void RunServer() { udpServer = new UdpClient(serverIpEndPoint.Port); uint IOC_IN = 0x80000000; uint IOC_VENDOR = 0x18000000; uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; udpServer.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); var remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); Task.Run(() => { while (true) { try { byte[] receiveBytes = udpServer.Receive(ref remoteIpEndPoint); var returnData = Encoding.ASCII.GetString(receiveBytes); var msg = Newtonsoft.Json.JsonConvert.DeserializeObject(returnData); lock (locker) { #if DEBUG WriteLine($"本次接收:{ remoteIpEndPoint.Address.ToString() }:{ remoteIpEndPoint.Port }收到消息:{ returnData }"); #endif dispatcher.Invoke(() => { if (!Clients.Any(c => c.Equals(remoteIpEndPoint))) { Clients.Add(new HostModel { IPEndPoint = remoteIpEndPoint, LastActiveTime = DateTime.Now, RouteId = msg.RouteId, MemberId = msg.MemberId, ShowVirtual = msg.ShowVirtual }); } else { if (msg.CommandType == 0) { var client = Clients.FirstOrDefault(n => n.Equals(remoteIpEndPoint)); client.LastActiveTime = DateTime.Now; client.ShowVirtual = msg.ShowVirtual; } else if(msg.CommandType == 1) { receiveMes.Add(msg); } } }); //if (timer.AutoReset == false) //{ // timer.AutoReset = true; //} } } catch (Exception e) { Log.Error("RunServer:" + e.Message); } } }); } private void NotifyClient() { try { lock (locker) { //加入虚拟人物消息 var virtualData = mapRecordRankingHander.GetVirtualUserData(); WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-当前在线人数:" + Clients.Count + "-当前虚拟人数:" + virtualData.Count); #if DEBUG WriteLine($"在线人:{Newtonsoft.Json.JsonConvert.SerializeObject(receiveMes)}"); //\r\n虚拟人:{Newtonsoft.Json.JsonConvert.SerializeObject(virtualData)} #endif receiveMes.AddRange(virtualData); SendMessage(Clients, receiveMes); dispatcher.Invoke(() => { Customers.Clear(); foreach (var item in receiveMes) { if (Customers.Any(c => c.MemberId == item.MemberId)) { continue; } Customers.Add(item); } //移除下线的客户端 for (int i = 0; i < receiveMes.Count; i++) { if (receiveMes[i].exit && !receiveMes[i].IsVirtual)//客户端退出,并且不是虚拟的人物 { //这个地方有严重的逻辑错误(虚拟的人物不能和真实的人用同一个名字) var info = Clients.FirstOrDefault(n => n.MemberId == receiveMes[i].MemberId); if (info != null) { Clients.Remove(info); } } } receiveMes.Clear();//删除已经发送的数据 //clients.RemoveAll(i => i.Expire);//移除5钟内连接不上的客户端 Clients.ToList().ForEach(item => { if (item.Expire) { Clients.Remove(item); } }); }); } //更新虚拟人物信息 mapRecordRankingHander.RemoveEndAndAddNewVirtualUser(); } catch (Exception e) { Log.Error($"NotifyClient:{ e.Message }\r\n{ e.StackTrace }"); } } private static void SendMessage(Collection clients, List msgModels) { string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(msgModels.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 })); var data = Encoding.ASCII.GetBytes(jsonString); foreach (var item in clients) { try { udpServer.Send(data, data.Length, item.IPEndPoint); } catch (Exception e) { Log.Error($"{ item.IPEndPoint.ToString() }:{ e.Message }\r\n{ e.StackTrace }"); } } } void WriteLine(string str) { Debug.WriteLine(str); } } }