Before Rebuild NetProvider

This commit is contained in:
CortexCore
2025-01-24 10:36:58 +08:00
parent 0823a00396
commit 4b72602bfa
13 changed files with 402 additions and 387 deletions

View File

@@ -7,10 +7,9 @@ namespace BITKit.Net
public static readonly KcpConfig Config = new KcpConfig(
NoDelay: true,
DualMode: false,
Interval: 8, // 1ms so at interval code at least runs.
Interval: 1, // 1ms so at interval code at least runs.
Timeout: 8000,
CongestionWindow: false
)
{
SendWindowSize = Kcp.WND_SND * 1000,

View File

@@ -13,6 +13,7 @@ using System.Net;
using System.Numerics;
using System.Reflection;
using System.Text;
using System.Threading;
using BITKit.Net.Examples;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
@@ -22,6 +23,7 @@ namespace BITKit.Net
{
public class KcpNetClient:INetClient,INetProvider
{
private readonly NetProviderCommon _common = new();
private readonly ILogger<KcpNetClient> _logger;
public KcpNetClient(ILogger<KcpNetClient> logger)
{
@@ -40,15 +42,24 @@ namespace BITKit.Net
Id = x.Id;
});
_isConnected.AddListener(ConnectionCallback);
AddCommandListener<SimplePing>(F);
return;
UniTask<SimplePing> F(SimplePing p)
{
p.EndTime = DateTime.Now;
return UniTask.FromResult(p);
}
}
public event Action OnStartConnect;
public event Action OnConnected;
public event Action OnDisconnected;
public event Action OnConnectedFailed;
public uint TickRate { get; set; } = 8;
public bool IsConnected => _isConnected;
public bool IsConnecting { get; private set; }
public double RpcTimeOut { get; set; } = 5;
public bool AutoReconnect { get; set; } = true;
public float2 Traffic { get; private set; }
public bool ManualTick { get; set; }
@@ -68,25 +79,17 @@ namespace BITKit.Net
AutoReset = true
};
private readonly GenericEvent _events = new();
private readonly ValidHandle _isConnected = new();
private bool _userConnected;
private int _index = int.MinValue;
private readonly ConcurrentDictionary<int, object> _p2p = new();
private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = new();
private readonly ConcurrentDictionary<string,MethodInfo> _rpcMethods = new();
private readonly ConcurrentDictionary<string,EventInfo> _rpcEvents = new();
private readonly ConcurrentDictionary<string,object> _rpcHandles = new();
private DateTime _lastHeartbeat = DateTime.Now;
private DateTime _now = DateTime.Now;
private TimeSpan _interval = TimeSpan.FromMilliseconds(100);
private string _connectedAddress = "127.0.0.1";
private ushort _connectedPort = 27014;
private readonly byte[] _heartBeat = new byte[] { (byte)NetCommandType.Heartbeat };
private async void ConnectionCallback(bool x)
{
await BITApp.SwitchToMainThread();
@@ -136,6 +139,7 @@ namespace BITKit.Net
return false;
}
_userConnected = true;
//如果address是域名,解析为Ip
if (address.Contains("."))
{
@@ -170,19 +174,15 @@ namespace BITKit.Net
_timer.Start();
_interval = TimeSpan.FromMilliseconds(_timer.Interval);
HandShake();
await BITApp.SwitchToMainThread();
for (var i = 0; i < 5; i++)
{
_client.Send(new[] { (byte)NetCommandType.Heartbeat }, KcpChannel.Reliable);
Traffic += new float2(1, 0);
if (_client.connected)
{
HandShake();
_client.Send(new[] { (byte)NetCommandType.Heartbeat }, KcpChannel.Reliable);
Traffic += new float2(1, 0);
}
_client.Tick();
await Task.Delay(100);
}
if (_client.connected)
{
@@ -192,6 +192,7 @@ namespace BITKit.Net
_connectedAddress = address;
_connectedPort = port;
return _client.connected;
}
@@ -247,7 +248,7 @@ namespace BITKit.Net
if (BITApp.SynchronizationContext is not null)
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext,
BITApp.CancellationToken);
_events.Invoke(command.GetType().FullName, command);
_common.Events.Invoke(command.GetType().FullName, command);
}
catch (OperationCanceledException)
{
@@ -272,21 +273,24 @@ namespace BITKit.Net
case NetCommandType.ReturnToClient:
var id = reader.ReadInt32();
try
{
if (reader.ReadBoolean())
if (_common.P2P.TryRemove(id, out var source))
{
var value = BITBinary.Read(reader);
_p2p.TryAdd(id,value);
if (reader.ReadBoolean())
{
var value = BITBinary.Read(reader);
source.TrySetResult(value);
}
else
{
var message = reader.ReadString();
source.TrySetException(new Exception(message));
}
}
else
{
var message = reader.ReadString();
_p2p.TryAdd(id,new Exception(message));
_logger.LogWarning($"ID为{id}的请求未注册回调");
}
}
catch (Exception e)
@@ -314,10 +318,10 @@ namespace BITKit.Net
var pars = BITBinary.Read(reader).As<object[]>();
if (_rpcMethods.TryGetValue(path, out var methodInfo))
if (_common.RpcMethods.TryGetValue(path, out var methodInfo))
{
var isAwaitable = methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
var handle = _rpcHandles[path];
var handle = _common.RpcHandles[path];
try
{
@@ -342,9 +346,9 @@ namespace BITKit.Net
returnWriter.Write(true);
BITBinary.Write(returnWriter, value);
}
else if (_rpcEvents.TryGetValue(path, out var eventInfo))
else if (_common.RpcEvents.TryGetValue(path, out var eventInfo))
{
var handle = _rpcHandles[path];
var handle = _common.RpcHandles[path];
var fieldInfo = handle.GetType().GetField(eventInfo.Name,ReflectionHelper.Flags)!;
var eventDelegate = fieldInfo.GetValue(handle) as MulticastDelegate;
@@ -364,7 +368,7 @@ namespace BITKit.Net
{
var commandObj = BITBinary.Read(reader)
.As<object[]>()[0];
var func = _rpc[commandObj.GetType()!.FullName!];
var func = _common.Rpc[commandObj.GetType()!.FullName!];
value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
}
@@ -392,11 +396,11 @@ namespace BITKit.Net
{
var rpcName = reader.ReadString();
var pars = BITBinary.Read(reader).As<object[]>();
if (_rpcMethods.TryGetValue(rpcName, out var methodInfo))
if (_common.RpcMethods.TryGetValue(rpcName, out var methodInfo))
{
try
{
methodInfo.Invoke(_rpcHandles[rpcName], pars);
methodInfo.Invoke(_common.RpcHandles[rpcName], pars);
}
catch (TargetException targetException)
{
@@ -434,9 +438,9 @@ namespace BITKit.Net
}
}
else if (_rpcEvents.TryGetValue(rpcName, out var eventInfo))
else if (_common.RpcEvents.TryGetValue(rpcName, out var eventInfo))
{
var handle = _rpcHandles[rpcName];
var handle = _common.RpcHandles[rpcName];
var fieldInfo = handle.GetType().GetField(eventInfo.Name,ReflectionHelper.Flags)!;
var eventDelegate = fieldInfo.GetValue(handle) as MulticastDelegate;
@@ -517,13 +521,13 @@ namespace BITKit.Net
_commandQueue.Enqueue(bytes);
}
public async UniTask<T> GetFromServer<T>(string path = default,params object[] pars)
public async UniTask<T> GetFromServer<T>(string path = default, params object[] pars)
{
if (IsConnected is false)
{
throw new NetOfflineException();
}
//await UniTask.SwitchToThreadPool();
var id = _index++;
var ms = new MemoryStream();
var writer = new BinaryWriter(ms);
@@ -538,95 +542,63 @@ namespace BITKit.Net
writer.Write(true);
writer.Write(path);
}
BITBinary.Write(writer,pars);
if (pars.Length is 0)
{
pars = new[] { System.Activator.CreateInstance<T>() as object };
}
BITBinary.Write(writer, pars);
var bytes = ms.ToArray();
await ms.DisposeAsync();
await writer.DisposeAsync();
_commandQueue.Enqueue(bytes);
var startTime = _now;
while (true)
{
if (IsConnected is false)
{
throw new NetOfflineException();
}
if ((_now - startTime).TotalSeconds > RpcTimeOut)
{
if (string.IsNullOrEmpty(path))
{
throw new TimeoutException("请求超时或已断开连接");
}
throw new TimeoutException($"请求超时或已断开连接,请求为{path}");
}
if (_p2p.TryRemove(id, out var value))
{
await BITApp.SwitchToMainThread();
if (value is Exception e)
{
throw new InGameException(e.Message);
}
if (UniTask.CompletedTask is T t)
{
return t;
}
return value.As<T>();
}
await Task.Delay(_interval);
_commandQueue.Enqueue(bytes);
var source = new UniTaskCompletionSource<object>();
_common.P2P.TryAdd(id, source);
var timeoutCts = new CancellationTokenSource();
timeoutCts.CancelAfter(5000); // 设置超时时间
var value = await source.Task.AttachExternalCancellation(timeoutCts.Token);
if (value is Exception e)
{
throw new InGameException(e.Message);
}
if (UniTask.CompletedTask is T t)
{
return t;
}
return value.As<T>();
}
public UniTask<T> GetFromClient<T>(int id,string path, params object[] pars)
{
throw new NotImplementedException();
}
public void AddRpcHandle(object rpcHandle)
{
var reportBuilder = new StringBuilder();
reportBuilder.AppendLine($"正在通过反射注册{rpcHandle.GetType().Name}");
foreach (var methodInfo in rpcHandle.GetType().GetMethods())
{
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
if (att is null) continue;
_rpcMethods.AddOrUpdate(methodInfo.Name, methodInfo, (s, info) => methodInfo);
_rpcHandles.AddOrUpdate(methodInfo.Name, rpcHandle, (s, o) => rpcHandle);
reportBuilder.AppendLine($"Add [{methodInfo.Name}] as MethodInfo");
}
foreach (var eventInfo in rpcHandle.GetType().GetEvents())
{
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>();
if (att is null) continue;
_rpcEvents.TryAdd(eventInfo.Name, eventInfo);
_rpcHandles.TryAdd(eventInfo.Name, rpcHandle);
reportBuilder.AppendLine($"Add [{eventInfo.Name}] as EventInfo");
}
_logger.LogInformation(reportBuilder.ToString());
_common.AddRpcHandle(rpcHandle);
}
public void AddCommandListener<T>(Action<T> handle)
{
_events.AddListener<T>(handle);
_common. Events.AddListener<T>(handle);
}
public void AddCommandListener<T>(Func<T,UniTask<T>> func)
{
_rpc.TryAdd(typeof(T).FullName, F);
_common. Rpc.TryAdd(typeof(T).FullName, F);
return;
async UniTask<object> F(object o)
@@ -637,12 +609,12 @@ namespace BITKit.Net
public void RemoveCommandListener<T>(Func<T,UniTask<T>> func)
{
_rpc.TryRemove(typeof(T).FullName, out _);
_common. Rpc.TryRemove(typeof(T).FullName, out _);
}
public void RemoveCommandListener<T>(Action<T> handle)
{
_events.RemoveListener<T>(handle);
_common. Events.RemoveListener<T>(handle);
}
public void SendRT(string rpcName, params object[] pars)
@@ -709,7 +681,7 @@ namespace BITKit.Net
_client.Send(bytes, KcpChannel.Reliable);
}
Traffic+=new float2(1,0);
_client.Send(_heartBeat, KcpChannel.Unreliable);
_client.Send(_common.HeartBeat, KcpChannel.Unreliable);
}
else
{

View File

@@ -11,23 +11,27 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Markup;
using BITKit.Net.Examples;
using Microsoft.Extensions.Logging;
namespace BITKit.Net
{
public class KCPNetServer:INetServer,INetProvider
{
private readonly NetProviderCommon _common = new();
private readonly ILogger<KCPNetServer> _logger;
public string Name { get; set; } = "Default";
public int TickRate { get; set; } = 16;
public uint TickRate { get; set; } = 8;
public bool ManualTick { get; set; }
public event Action<int> OnClientConnected;
public event Action<int> OnClientDisconnected;
public event Action OnStartServer;
public event Action OnStopServer;
private readonly KcpServer server;
private readonly GenericEvent _events = new();
private bool _isStarted;
private readonly Timer _timer = new(100)
{
@@ -35,25 +39,14 @@ namespace BITKit.Net
};
private int _index = 1001;
private readonly ConcurrentDictionary<int, object> _p2p = new();
private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = new();
private readonly ConcurrentDictionary<string,MethodInfo> _rpcMethods = new();
private readonly ConcurrentDictionary<string,EventInfo> _rpcEvents = new();
private readonly ConcurrentDictionary<string,object> _rpcHandles = new();
private readonly ConcurrentDictionary<int,DateTime> _lastHeartbeat = new();
private readonly ConcurrentQueue<(int id,byte[] bytes)> _sendQueue = new();
private readonly ConcurrentDictionary<int,int> _dropCount = new();
private DateTime _now=DateTime.Now;
private TimeSpan _interval=TimeSpan.FromSeconds(0.32);
private readonly byte[] _heartBeat = new byte[] { (byte)NetCommandType.Heartbeat };
private DateTime _now=DateTime.UtcNow;
[NetRpc]
public event Action<int, float, bool> OnNetRpcTest;
public KCPNetServer()
public KCPNetServer(ILogger<KCPNetServer> logger)
{
_logger = logger;
server = new KcpServer(
OnConnected,
OnData,
@@ -70,7 +63,7 @@ namespace BITKit.Net
OnNetRpcTest += (_int, _float, _bool) =>
{
BIT4Log.Log<KCPNetServer>($"已收到Rpc测试:{_int},{_float},{_bool}");
_logger.LogInformation($"已收到Rpc测试:{_int},{_float},{_bool}");
};
return;
@@ -93,23 +86,18 @@ namespace BITKit.Net
foreach (var id in Connections.Keys.ToArray())
{
server.Send(id,_heartBeat , KcpChannel.Unreliable);
if (!_lastHeartbeat.TryGetValue(id, out var time)) continue;
server.Send(id,_common.HeartBeat , KcpChannel.Unreliable);
if (!_common.LastHeartbeat.TryGetValue(id, out var time)) continue;
if (!((_now - time).TotalSeconds > 3)) continue;
server.Disconnect(id);
_lastHeartbeat.TryRemove(id);
BIT4Log.Log<KCPNetServer>($"{Name}:链接{id}超时,已断开");
_common.LastHeartbeat.TryRemove(id);
_logger.LogInformation($"{Name}:链接{id}超时,已断开");
}
if (server.IsActive() is false) return;
server.Tick();
//BIT4Log.Log<KCPNetServer>($"{Name}目前有{server.connections.Count}个链接");
_dropCount.Clear();
while (_sendQueue.TryDequeue(out var value))
_common.DropCount.Clear();
while (_common.SendQueue.TryDequeue(out var value))
{
if (server.connections.ContainsKey(value.id))
@@ -120,13 +108,15 @@ namespace BITKit.Net
{
int UpdateValueFactory(int i, int i1) => i1 + value.bytes.Length;
_dropCount.AddOrUpdate(value.id,value.bytes.Length,UpdateValueFactory);
_common.DropCount.AddOrUpdate(value.id,value.bytes.Length,UpdateValueFactory);
}
}
foreach (var (id,length) in _dropCount)
foreach (var (id,length) in _common.DropCount)
{
BIT4Log.Log<KCPNetServer>($"未找到链接:{id},已丢弃字节数量:{length}");
_logger.LogInformation($"未找到链接:{id},已丢弃字节数量:{length}");
}
server.Tick();
}
catch (SocketException)
{
@@ -134,7 +124,7 @@ namespace BITKit.Net
}
catch (Exception exception)
{
BIT4Log.LogException(exception);
_logger.LogCritical(exception,exception.Message);
}
}
@@ -148,7 +138,6 @@ namespace BITKit.Net
if (TickRate > 0)
{
_timer.Interval = 1000f / TickRate;
_interval = TimeSpan.FromSeconds(1.0 / TickRate);
}
OnStartServer?.Invoke();
@@ -156,7 +145,7 @@ namespace BITKit.Net
if (ManualTick is false)
_timer.Start();
_isStarted = true;
BIT4Log.Log<KCPNetServer>($"已启动KCP服务器:{port}");
_logger.LogInformation($"已启动KCP服务器:{port}");
}
else
{
@@ -172,7 +161,7 @@ namespace BITKit.Net
server.Stop();
OnStopServer?.Invoke();
_timer.Stop();
BIT4Log.Log<KCPNetServer>($"已停止KCP服务器");
_logger.LogInformation($"已停止KCP服务器");
}
else
{
@@ -186,7 +175,7 @@ namespace BITKit.Net
using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.Message);
writer.Write(message);
_sendQueue.Enqueue((id,ms.ToArray()));
_common.SendQueue.Enqueue((id,ms.ToArray()));
}
public void SendMessageToAll(string message)
@@ -211,7 +200,7 @@ namespace BITKit.Net
}
catch (SocketException)
{
BIT4Log.Log<INetServer>("有用户断开连接,如有异常请检查");
_logger.LogInformation("有用户断开连接,如有异常请检查");
}
}
@@ -225,30 +214,23 @@ namespace BITKit.Net
private void OnConnectedInternel(int id)
{
//server.connections[id].peer.kcp.SetInterval(TickRate);
OnClientConnected?.Invoke(id);
ClientCommand(id,new NetClientAllocateIdCommand
{
Id = id,
Ip = server.connections[id].remoteEndPoint.ToString()
});
BIT4Log.Log<KCPNetServer>($"{id}已连接到:{Name}");
_logger.LogInformation($"{id}已连接到:{Name}");
SendMessageToClient(id, $"成功连接到服务器:{Name}");
}
private void OnConnected(int Id)
{
// OnClientConnected?.Invoke(Id);
// ClientCommand(Id,new NetClientAllocateIdCommand
// {
// Id = Id,
// Ip = server.connections[Id].remoteEndPoint.ToString()
// });
// BIT4Log.Log<KCPNetServer>($"{Id}已连接到:{Name}");
// SendMessageToClient(Id, $"成功连接到服务器:{Name}");
}
private void OnDisconnect(int Id)
{
OnClientDisconnected?.Invoke(Id);
BIT4Log.Log<KCPNetServer>($"{Id}已断开");
_logger.LogInformation($"{Id}已断开");
}
private void OnData(int Id, ArraySegment<byte> bytes, KcpChannel channel)
@@ -275,44 +257,44 @@ namespace BITKit.Net
switch (type)
{
case NetCommandType.Message:
BIT4Log.Log<KCPNetServer>($"已收到消息,{Id}:{reader.ReadString()}");
_logger.LogInformation($"已收到消息,{Id}:{reader.ReadString()}");
break;
case NetCommandType.Command:
var command = BITBinary.Read(reader);
if (command is object[] { Length: 1 } objs) command = objs[0];
//BIT4Log.Log<KCPNetServer>($"已收到指令:{command},值:\n{JsonConvert.SerializeObject(command, Formatting.Indented)}");
_events.Invoke(command.GetType().FullName, command);
_common.Events.Invoke(command.GetType().FullName, command);
(int Id, object Command) tuple = (Id, command);
_events.InvokeDirect(command.GetType().FullName, tuple);
_common.Events.InvokeDirect(command.GetType().FullName, tuple);
break;
case NetCommandType.Heartbeat:
if (Connections.ContainsKey(Id))
{
_lastHeartbeat.AddOrUpdate(Id,OnAdd,OnUpdate);
if (_common.LastHeartbeat.ContainsKey(Id))
{
_common.LastHeartbeat[Id] = _now;
}
else
{
_common.LastHeartbeat.TryAdd(Id, _now);
OnConnectedInternel(Id);
}
}
break;
DateTime OnAdd(int arg)
{
OnConnectedInternel(Id);
return _now;
}
DateTime OnUpdate(int arg1, DateTime arg2)
{
return _now;
}
case NetCommandType.AllClientCommand:
foreach (var id in server.connections.Keys.ToArray())
{
_sendQueue.Enqueue((id,bytes.ToArray()));
_common.SendQueue.Enqueue((id,bytes.ToArray()));
}
break;
case NetCommandType.TargetCommand:
var targetId = reader.ReadInt32();
_sendQueue.Enqueue((targetId,bytes.ToArray()));
_common.SendQueue.Enqueue((targetId,bytes.ToArray()));
break;
case NetCommandType.Ping:
_sendQueue.Enqueue((Id,new byte[] { (byte)NetCommandType.Ping }));
_common.SendQueue.Enqueue((Id,new byte[] { (byte)NetCommandType.Ping }));
break;
case NetCommandType.GetFromServer:
{
@@ -329,10 +311,10 @@ namespace BITKit.Net
var pars = BITBinary.Read(reader).As<object[]>();
object value = null;
if (_rpcMethods.TryGetValue(path, out var methodInfo))
if (_common.RpcMethods.TryGetValue(path, out var methodInfo))
{
var isAwaitable = methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
var handle = _rpcHandles[path];
var handle = _common.RpcHandles[path];
if (methodInfo.GetParameters().Length is 0)
{
@@ -374,7 +356,7 @@ namespace BITKit.Net
returnWriter.Write(e.Message);
var _bytes = returnMS.ToArray();
_sendQueue.Enqueue((Id,_bytes));
_common.SendQueue.Enqueue((Id,_bytes));
if (e is InGameException inGameException)
{
@@ -386,9 +368,9 @@ namespace BITKit.Net
}
returnWriter.Write(true);
}else if (_rpcEvents.TryGetValue(path, out var eventInfo))
}else if (_common.RpcEvents.TryGetValue(path, out var eventInfo))
{
var handle = _rpcHandles[path];
var handle = _common.RpcHandles[path];
var fieldInfo = handle.GetType().GetField(eventInfo.Name,ReflectionHelper.Flags)!;
var eventDelegate = fieldInfo.GetValue(handle) as MulticastDelegate;
@@ -409,10 +391,11 @@ namespace BITKit.Net
}
else
{
var commandObj = BITBinary.Read(reader)
.As<object[]>()[0];
var commandObjs = BITBinary.Read(reader);
var commandObj = commandObjs.As<object[]>()[0];
var funcName = commandObj.GetType()!.FullName!;
if (_rpc.TryGetValue(funcName, out var func))
if (_common.Rpc.TryGetValue(funcName, out var func))
{
var value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
returnWriter.Write(true);
@@ -425,8 +408,7 @@ namespace BITKit.Net
}
{
var _bytes = returnMS.ToArray();
_sendQueue.Enqueue((Id,_bytes));
_common.SendQueue.Enqueue((Id,returnMS.ToArray()));
}
}
@@ -434,21 +416,31 @@ namespace BITKit.Net
case NetCommandType.ReturnToServer:
{
var id = reader.ReadInt32();
if (reader.ReadBoolean())
if (_common.P2P.TryRemove(id, out var source))
{
var value = BITBinary.Read(reader);
_p2p.TryAdd(id, value);
if (reader.ReadBoolean())
{
var value = BITBinary.Read(reader);
source.TrySetResult(value);
}
else
{
var message = reader.ReadString();
source.TrySetException(new Exception(message));
}
}
else
{
var message = reader.ReadString();
_p2p.TryAdd(id, new Exception(message));
_logger.LogWarning($"ID为{id}的请求未注册回调");
}
}
break;
default:
BIT4Log.Log<KCPNetServer>($"未知消息类型:{type},字节:{(byte)type}");
BIT4Log.Log<KCPNetServer>(
_logger.LogInformation($"未知消息类型:{type},字节:{(byte)type}");
_logger.LogInformation(
$"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
break;
}
@@ -466,12 +458,12 @@ namespace BITKit.Net
private void OnError(int Id, ErrorCode errorCode, string message)
{
BIT4Log.Log<KCPNetServer>($"异常:{errorCode},{message}");
_logger.LogInformation($"异常:{errorCode},{message}");
}
public void ServerCommand<T>(T command = default)
{
_events.Invoke<T>(command);
_common. Events.Invoke<T>(command);
}
public void AllClientCommand<T>(T command = default)
@@ -488,7 +480,7 @@ namespace BITKit.Net
using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.Command);
BITBinary.Write(writer,command);
_sendQueue.Enqueue((id,ms.ToArray()));
_common.SendQueue.Enqueue((id,ms.ToArray()));
}
public UniTask<T> GetFromServer<T>(string path=default,params object[] pars)
@@ -520,16 +512,19 @@ namespace BITKit.Net
await ms.DisposeAsync();
await writer.DisposeAsync();
_sendQueue.Enqueue((id,bytes));
var startTime = _now;
while (true)
{
var time = _now - startTime;
if(time.TotalSeconds>5)
throw new TimeoutException($"等待超时,Id:{id},时间{time.TotalSeconds}");
_common.SendQueue.Enqueue((id,bytes));
if (_p2p.TryRemove(index, out var value))
{
var source = new UniTaskCompletionSource<object>();
_common.P2P.TryAdd(index, source);
var timeoutCts = new CancellationTokenSource();
timeoutCts.CancelAfter(5000); // 设置超时时间
var value =await source.Task.AttachExternalCancellation(timeoutCts.Token);
//await BITApp.SwitchToMainThread();
if (value is Exception e)
{
@@ -544,9 +539,6 @@ namespace BITKit.Net
return default;
}
return (T)value;
}
await Task.Delay(_interval);
}
}
public void AddRpcHandle(object rpcHandle)
@@ -555,16 +547,16 @@ namespace BITKit.Net
{
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>(true);
if(att is null)continue;
_rpcMethods.TryAdd(methodInfo.Name, methodInfo);
_rpcHandles.TryAdd(methodInfo.Name, rpcHandle);
_common.RpcMethods.TryAdd(methodInfo.Name, methodInfo);
_common.RpcHandles.TryAdd(methodInfo.Name, rpcHandle);
}
foreach (var eventInfo in rpcHandle.GetType().GetEvents())
{
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>(true);
if(att is null)continue;
_rpcEvents.TryAdd(eventInfo.Name, eventInfo);
_rpcHandles.TryAdd(eventInfo.Name, rpcHandle);
_common. RpcEvents.TryAdd(eventInfo.Name, eventInfo);
_common. RpcHandles.TryAdd(eventInfo.Name, rpcHandle);
}
}
@@ -582,12 +574,12 @@ namespace BITKit.Net
public void AddCommandListener<T>(Action<T> handle)
{
_events.AddListener<T>(handle);
_common.Events.AddListener<T>(handle);
}
public void AddCommandListener<T>(Func<T,UniTask<T>> func)
{
_rpc.TryAdd(typeof(T).FullName, F);
_common.Rpc.TryAdd(typeof(T).FullName, F);
return;
async UniTask<object> F(object o)
@@ -597,11 +589,11 @@ namespace BITKit.Net
}
public void RemoveCommandListener<T>(Func<T,UniTask<T>> func)
{
_rpc.TryRemove(typeof(T).FullName, out _);
_common. Rpc.TryRemove(typeof(T).FullName, out _);
}
public void AddCommandListenerWithId<T>(Action<int, T> handle)
{
_events.AddListenerDirect(typeof(T).FullName, Callback);
_common.Events.AddListenerDirect(typeof(T).FullName, Callback);
return;
void Callback(object value)
@@ -624,7 +616,7 @@ namespace BITKit.Net
public void RemoveCommandListener<T>(Action<T> handle)
{
_events.RemoveListener<T>(handle);
_common. Events.RemoveListener<T>(handle);
}
public void RemoveCommandListener<T>(Func<string, T> func)
@@ -645,7 +637,7 @@ namespace BITKit.Net
writer.Write(rpcName);
BITBinary.Write(writer,pars);
var bytes = ms.ToArray();
_sendQueue.Enqueue((id,bytes));
_common.SendQueue.Enqueue((id,bytes));
}
public void SendAllRT(string rpcName, params object[] pars)
@@ -658,7 +650,7 @@ namespace BITKit.Net
var bytes = ms.ToArray();
foreach (var id in server.connections.Keys)
{
_sendQueue.Enqueue((id,bytes));
_common.SendQueue.Enqueue((id,bytes));
}
}
}