powerfun-new-net/ViewModels/MainWindowViewModel.cs
2020-12-16 13:47:20 +08:00

237 lines
9.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<HostModel> Clients { get; private set; } = new ObservableCollection<HostModel>();
private static List<MsgModel> receiveMes = new List<MsgModel>();
private static object locker = new object();
public static System.Timers.Timer timer;
private static MapRecordRankingHander mapRecordRankingHander;
private Dispatcher dispatcher;
public ObservableCollection<MsgModel> Customers { get; private set; } =
new ObservableCollection<MsgModel>();
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<MsgModel>(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<HostModel> clients, List<MsgModel> 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,
m.Saved
}));
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);
}
}
}