powerfun-new-net/ViewModels/MainWindowViewModel.cs

309 lines
11 KiB
C#
Raw Normal View History

2020-10-13 08:54:24 +08:00
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;
2020-10-13 08:54:24 +08:00
namespace OnlineUserPool.ViewModels
{
public class MainWindowViewModel : BindableBase
{
2020-10-13 08:54:24 +08:00
public ObservableCollection<HostModel> Clients { get; private set; } = new ObservableCollection<HostModel>();
private static ConcurrentBag<MsgModel> receiveMes = new ConcurrentBag<MsgModel>();
2020-10-13 08:54:24 +08:00
private static object locker = new object();
public static System.Timers.Timer timer;
private static IHandle mapRecordRankingHander;
2020-10-13 08:54:24 +08:00
private Dispatcher dispatcher;
public ObservableCollection<MsgModel> Customers { get; private set; } =
new ObservableCollection<MsgModel>();
2020-10-27 10:20:47 +08:00
private string _Title = "";
public string Title
{
get { return _Title; }
set
{
SetProperty(ref _Title, value);
}
}
2020-10-13 08:54:24 +08:00
private string _SendDataSize = "";
public string SendDataSize
{
get { return _SendDataSize; }
set
{
SetProperty(ref _SendDataSize, value);
}
}
//private IService _udpService;
2020-10-13 08:54:24 +08:00
public MainWindowViewModel()
{
2021-06-24 09:20:01 +08:00
Title = $"{ IPAddress.Any }:{ ConfigHelp.UdpPort }";
2020-10-27 10:20:47 +08:00
2020-10-13 08:54:24 +08:00
dispatcher = Dispatcher.CurrentDispatcher;
//Customers.Add("suntao");
WriteLine(DateTime.Now.ToShortDateString());
LogHelper.Init();
2021-06-24 09:20:01 +08:00
mapRecordRankingHander = new MultiUserHandle();//new MapRecordRankingHander();
//mapRecordRankingHander = new MultiUserHandle();
Log.Information($"初始化连接,当前地址:{ IPAddress.Any }:{ConfigHelp.UdpPort}");
new TcpService1().RunServer(ReceivedData);
//var tet = new System.Collections.Concurrent.ConcurrentBag<object>();
var _udpService = new UdpService();
_udpService.RunServer(ReceivedData);
2020-10-13 08:54:24 +08:00
Log.Information("服务启动成功");
timer = new System.Timers.Timer(1000);
timer.Elapsed += Timer_Elapsed;
timer.AutoReset = true;
timer.Start();
Log.Information("等待连接");
//Console.ReadKey();
}
private void ReceivedData(IPEndPoint remoteIpEndPoint, MsgModel msg, IService service)
2020-10-13 08:54:24 +08:00
{
dispatcher.Invoke(() =>
2020-10-13 08:54:24 +08:00
{
if (!Clients.Any(c => c.Equals(remoteIpEndPoint)))
2020-10-13 08:54:24 +08:00
{
Clients.Add(new HostModel
2020-10-13 08:54:24 +08:00
{
IPEndPoint = remoteIpEndPoint,
LastActiveTime = DateTime.Now,
RouteId = msg.RouteId,
MemberId = msg.MemberId,
//ShowVirtual = msg.ShowVirtual
V = msg.V,
Service = service
});
}
2020-10-13 08:54:24 +08:00
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);
2020-10-13 08:54:24 +08:00
}
});
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
NotifyClient();
}
2020-10-13 08:54:24 +08:00
private void NotifyClient()
{
try
{
2021-06-24 09:20:01 +08:00
if(!receiveMes.Any())
{
dispatcher.Invoke(() =>
{
Customers.Clear();
//删除已经发送的数据
//receiveMes.Clear();
//移除5钟内连接不上的客户端
Clients.ToList().ForEach(item =>
{
if (item.Expire)
{
Clients.Remove(item);
}
});
});
return;
}
2020-10-13 08:54:24 +08:00
lock (locker)
{
var list = CloneJson(receiveMes).ToList();
receiveMes.Clear();
2020-10-13 08:54:24 +08:00
//加入虚拟人物消息
var virtualData = mapRecordRankingHander.GetVirtualUserData();
WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-当前在线人数:" + Clients.Count + "-当前虚拟人数:" + virtualData.Count);
2020-10-13 08:54:24 +08:00
#if DEBUG
WriteLine($"在线人:{Newtonsoft.Json.JsonConvert.SerializeObject(list)}");
2020-10-13 08:54:24 +08:00
//\r\n虚拟人{Newtonsoft.Json.JsonConvert.SerializeObject(virtualData)}
#endif
list.AddRange(virtualData);
2020-10-13 08:54:24 +08:00
SendMessage(Clients, list);
2020-10-13 08:54:24 +08:00
dispatcher.Invoke(() =>
{
Customers.Clear();
foreach (var item in list)
2020-10-13 08:54:24 +08:00
{
2020-10-27 10:20:47 +08:00
if (Customers.Any(c => c.MemberId == item.MemberId))
{
continue;
}
2020-10-13 08:54:24 +08:00
Customers.Add(item);
}
//移除下线的客户端
for (int i = 0; i < list.Count; i++)
2020-10-13 08:54:24 +08:00
{
if (list[i].exit && list[i].MemberId >0)//客户端退出,并且不是虚拟的人物
2020-10-13 08:54:24 +08:00
{
//这个地方有严重的逻辑错误(虚拟的人物不能和真实的人用同一个名字)
var info = Clients.FirstOrDefault(n => n.MemberId == list[i].MemberId);
2020-10-13 08:54:24 +08:00
if (info != null)
{
Clients.Remove(info);
}
}
}
//删除已经发送的数据
//receiveMes.Clear();
//移除5钟内连接不上的客户端
2020-10-13 08:54:24 +08:00
Clients.ToList().ForEach(item =>
{
if (item.Expire)
{
Clients.Remove(item);
}
});
});
}
//更新虚拟人物信息
mapRecordRankingHander.RemoveEndAndAddNewVirtualUser(Customers.Count);
2020-10-13 08:54:24 +08:00
}
catch (Exception e)
{
2020-10-27 10:20:47 +08:00
Log.Error($"NotifyClient:{ e.Message }\r\n{ e.StackTrace }");
2020-10-13 08:54:24 +08:00
}
}
private void SendMessage(Collection<HostModel> clients, List<MsgModel> msgModels)
2020-10-13 08:54:24 +08:00
{
2021-06-24 09:20:01 +08:00
if (!clients.Any())
{
return;
}
var clients1 = clients.ToList();
2021-06-24 09:20:01 +08:00
var list = CloneJson<List<MsgModel>>(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,
2020-12-16 13:47:20 +08:00
m.Competitionid,
m.Saved,
}));
2020-10-13 08:54:24 +08:00
var data = Encoding.ASCII.GetBytes(jsonString);
2021-06-24 09:20:01 +08:00
//SendDataSize = (data.Length/1000D).ToString() +"KB";
var strV1 = string.Join("|", list.Select(m => m.ToString(1)));
2021-06-24 09:20:01 +08:00
if (!string.IsNullOrWhiteSpace(strV1))
{
strV1 += "|";
}
//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.ASCII.GetBytes(strV1);
2021-06-24 09:20:01 +08:00
var dataV1ForUdp = strV1.Last() == '|' ? Encoding.ASCII.GetBytes(strV1.Substring(0, strV1.Length - 1)) : dataV1;
SendDataSize = $"\t单客户端数据包V1{ (strV1.Length/1000D) }KB一共占用带宽{ strV1.Length / 1000D * clients1.Count }KB";
foreach (var item in clients1)
2020-10-13 08:54:24 +08:00
{
try
{
if(item == null)
{
continue;
}
2021-06-24 09:20:01 +08:00
if((item.Service is UdpService) ==false)
{
continue;
}
if (item.V == 1)
2021-06-24 09:20:01 +08:00
{
item.Service.Send(dataV1ForUdp, dataV1ForUdp.Length, item.IPEndPoint);
}
else
{
item.Service.Send(data, data.Length, item.IPEndPoint);
}
2020-10-13 08:54:24 +08:00
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
Log.Error($"{ item.IPEndPoint.ToString() }:{ e.Message }\r\n{ e.StackTrace }");
2020-10-13 08:54:24 +08:00
}
}
2021-06-24 09:20:01 +08:00
var tcpClient = clients1.Where(c => c.Service is TcpService1).FirstOrDefault();
if(tcpClient != null)
{
tcpClient.Service.Send(dataV1, dataV1.Length, null);
}
2020-10-13 08:54:24 +08:00
}
void WriteLine(string str)
{
//Debug.WriteLine(str);
}
T CloneJson<T>(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<T>(JsonConvert.SerializeObject(source), deserializeSettings);
2020-10-13 08:54:24 +08:00
}
}
}