This commit is contained in:
CortexCore
2024-11-03 16:38:17 +08:00
parent 056e2cada5
commit 4ba741408d
4693 changed files with 2445 additions and 5443 deletions

View File

@@ -14,6 +14,7 @@ using System.Numerics;
using System.Reflection;
using System.Text;
using BITKit.Net.Examples;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Unity.Mathematics;
@@ -21,6 +22,26 @@ namespace BITKit.Net
{
public class KcpNetClient:INetClient,INetProvider
{
private readonly ILogger<KcpNetClient> _logger;
public KcpNetClient(ILogger<KcpNetClient> logger)
{
_logger = logger;
_client = new KcpClient(
OnConnectedInternal,
OnData,
OnDisconnectInternal,
OnError,
KCPNet.Config
);
_timer.Elapsed += Tick;
_logger.LogInformation("已创建KCP客户端");
AddCommandListener<NetClientAllocateIdCommand>(x =>
{
Id = x.Id;
});
_isConnected.AddListener(ConnectionCallback);
}
public event Action OnStartConnect;
public event Action OnConnected;
public event Action OnDisconnected;
@@ -29,14 +50,14 @@ namespace BITKit.Net
public bool IsConnecting { get; private set; }
public double RpcTimeOut { get; set; } = 5;
public bool AutoReconnect { get; set; } = true;
public float2 Traffic { get; set; }
public float2 Traffic { get; private set; }
public bool ManualTick { get; set; }
private readonly IntervalUpdate _reconnectInterval = new(1);
public int Ping { get; private set; }
public int Id { get; private set; } = -1;
private readonly KcpClient client;
private readonly KcpClient _client;
private readonly ConcurrentQueue<byte[]> _commandQueue = new();
@@ -50,7 +71,7 @@ namespace BITKit.Net
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();
@@ -64,23 +85,7 @@ namespace BITKit.Net
private ushort _connectedPort = 27014;
private readonly byte[] _heartBeat = new byte[] { (byte)NetCommandType.Heartbeat };
public KcpNetClient()
{
client = new KcpClient(
OnConnectedInternal,
OnData,
OnDisconnectInternal,
OnError,
KCPNet.Config
);
_timer.Elapsed += Tick;
BIT4Log.Log<KcpNetClient>("已创建KCP客户端");
AddCommandListener<NetClientAllocateIdCommand>(x =>
{
Id = x.Id;
});
_isConnected.AddListener(ConnectionCallback);
}
private async void ConnectionCallback(bool x)
{
@@ -88,12 +93,12 @@ namespace BITKit.Net
if (x)
{
OnConnected?.Invoke();
BIT4Log.Log<KcpNetClient>("连接成功");
_logger.LogInformation("连接成功");
}
else
{
OnDisconnected?.Invoke();
BIT4Log.Log<KcpNetClient>("连接已断开");
_logger.LogInformation("连接已断开");
}
}
@@ -104,9 +109,14 @@ namespace BITKit.Net
}
public async void Disconnect()
{
_userConnected = false;
DisconnectInternal();
}
private async void DisconnectInternal()
{
IsConnecting = false;
client.Disconnect();
_client.Disconnect();
_isConnected.RemoveElement(this);
_timer.Stop();
try
@@ -117,6 +127,7 @@ namespace BITKit.Net
catch (OperationCanceledException){}
}
private string _lastHostName;
public async UniTask<bool> Connect(string address = "127.0.0.1", ushort port = 27014)
{
if (IsConnecting)
@@ -124,7 +135,7 @@ namespace BITKit.Net
BIT4Log.Warning<KcpNetClient>("正在连接中");
return false;
}
_userConnected = true;
//如果address是域名,解析为Ip
if (address.Contains("."))
{
@@ -132,7 +143,11 @@ namespace BITKit.Net
if (ip.Length > 0)
{
address = ip[0].ToString();
BIT4Log.Log<KcpNetClient>($"解析域名:{address}");
if (_lastHostName != address)
{
_logger.LogInformation($"解析域名:{address},IP:{ip}");
_lastHostName = address;
}
}
}
@@ -143,7 +158,7 @@ namespace BITKit.Net
IsConnecting = true;
if (client.connected) return false;
if (_client.connected) return false;
await BITApp.SwitchToMainThread();
OnStartConnect?.Invoke();
await UniTask.SwitchToThreadPool();
@@ -151,7 +166,7 @@ namespace BITKit.Net
{
_lastHeartbeat = DateTime.Now;
client.Connect(address, port);
_client.Connect(address, port);
_timer.Start();
_interval = TimeSpan.FromMilliseconds(_timer.Interval);
@@ -163,13 +178,13 @@ namespace BITKit.Net
for (var i = 0; i < 5; i++)
{
client.Send(new[] { (byte)NetCommandType.Heartbeat }, KcpChannel.Reliable);
_client.Send(new[] { (byte)NetCommandType.Heartbeat }, KcpChannel.Reliable);
Traffic += new float2(1, 0);
client.Tick();
_client.Tick();
await Task.Delay(100);
}
if (client.connected)
if (_client.connected)
{
SendServerMessage(Environment.MachineName);
@@ -177,11 +192,11 @@ namespace BITKit.Net
_connectedAddress = address;
_connectedPort = port;
return client.connected;
return _client.connected;
}
OnConnectedFailed?.Invoke();
Disconnect();
DisconnectInternal();
IsConnecting = false;
return false;
@@ -220,7 +235,7 @@ namespace BITKit.Net
switch (type)
{
case NetCommandType.Message:
BIT4Log.Log<KcpNetClient>($"已收到消息:{reader.ReadString()}");
_logger.LogInformation($"已收到消息:{reader.ReadString()}");
break;
case NetCommandType.AllClientCommand:
case NetCommandType.Command:
@@ -424,7 +439,7 @@ namespace BITKit.Net
if (eventDelegate is null)
{
BIT4Log.Warning<KcpNetClient>($"未找到对应的事件:{rpcName}");
//BIT4Log.Warning<KcpNetClient>($"未找到对应的事件:{rpcName}");
}
else
{
@@ -443,9 +458,9 @@ namespace BITKit.Net
}
break;
default:
BIT4Log.Log<KcpNetClient>($"未知消息类型:{type},字节:{(byte)type}");
_logger.LogInformation($"未知消息类型:{type},字节:{(byte)type}");
if (bytes.Array != null)
BIT4Log.Log<KcpNetClient>(
_logger.LogInformation(
$"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
break;
}
@@ -456,17 +471,17 @@ namespace BITKit.Net
// if (BITApp.SynchronizationContext is not null)
// await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
// OnConnected?.Invoke();
// BIT4Log.Log<KcpNetClient>("已连接");
// _logger.LogInformation("已连接");
}
private async void OnDisconnectInternal()
{
//BIT4Log.Log<KcpNetClient>("连接被断开");
Disconnect();
// _logger.LogInformation("连接被断开");
DisconnectInternal();
}
private void OnError(ErrorCode errorCode, string message)
{
BIT4Log.Log<KcpNetClient>($"{client.remoteEndPoint}异常:{errorCode},{message}");
_logger.LogInformation($"{_client.remoteEndPoint}异常:{errorCode},{message}");
}
public void ServerCommand<T>(T command = default)
@@ -500,6 +515,10 @@ namespace BITKit.Net
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();
@@ -528,6 +547,10 @@ namespace BITKit.Net
while (true)
{
if (IsConnected is false)
{
throw new NetOfflineException();
}
if ((_now - startTime).TotalSeconds > RpcTimeOut)
{
await BITApp.SwitchToMainThread();
@@ -573,24 +596,25 @@ namespace BITKit.Net
foreach (var methodInfo in rpcHandle.GetType().GetMethods())
{
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
if(att is null)continue;
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;
if (att is null) continue;
_rpcEvents.TryAdd(eventInfo.Name, eventInfo);
_rpcHandles.TryAdd(eventInfo.Name, rpcHandle);
reportBuilder.AppendLine($"Add [{eventInfo.Name}] as EventInfo");
}
BIT4Log.Log<KcpNetClient>(reportBuilder);
_logger.LogInformation(reportBuilder.ToString());
}
public void AddCommandListener<T>(Action<T> handle)
@@ -621,6 +645,10 @@ namespace BITKit.Net
public void SendRT(string rpcName, params object[] pars)
{
if (IsConnected is false)
{
throw new NetOfflineException();
}
using var ms = new MemoryStream();
using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.GetFromServer);
@@ -650,36 +678,36 @@ namespace BITKit.Net
.Write(message)
.Build();
Traffic+=new float2(bytes.Length,0);
client.Send(bytes, KcpChannel.Reliable);
_client.Send(bytes, KcpChannel.Reliable);
}
#if UNITY_EDITOR
private readonly IntervalUpdate _pingInterval = new(1);
#endif
#endif
public void Tick()
{
_now = DateTime.Now;
if(_userConnected is false)return;
try
{
_now = DateTime.UtcNow;
if (client.connected)
if (_client.connected)
{
if (DateTime.Now - _lastHeartbeat > TimeSpan.FromSeconds(5))
{
BIT4Log.Warning<KcpNetClient>("心跳超时,自动断开");
Disconnect();
DisconnectInternal();
_commandQueue.Clear();
return;
}
while (_commandQueue.TryDequeue(out var bytes))
{
Traffic += new float2(bytes.Length, 0);
client.Send(bytes, KcpChannel.Reliable);
_client.Send(bytes, KcpChannel.Reliable);
}
Traffic+=new float2(1,0);
client.Send(_heartBeat, KcpChannel.Unreliable);
_client.Send(_heartBeat, KcpChannel.Unreliable);
}
else
{
@@ -696,16 +724,7 @@ namespace BITKit.Net
//BIT4Log.Warning<KcpNetClient>("连接已断开,清空指令队列");
}
}
#if UNITY_EDITOR
if (_pingInterval.AllowUpdate)
{
_lastPingTime = DateTime.Now;
client.Send(new[] { (byte)NetCommandType.Ping }, KcpChannel.Reliable);
}
#endif
client.Tick();
_client.Tick();
}
catch (Exception e)
{
@@ -718,7 +737,7 @@ namespace BITKit.Net
{
// send client to server
Traffic+=new float2(2,0);
client.Send(new byte[]{0x01, 0x02}, KcpChannel.Reliable);
_client.Send(new byte[]{0x01, 0x02}, KcpChannel.Reliable);
}
}
}

View File

@@ -101,7 +101,7 @@ namespace BITKit.Net
BIT4Log.Log<KCPNetServer>($"{Name}:链接{id}超时,已断开");
}
if (server.IsActive() is false || ManualTick) return;
if (server.IsActive() is false) return;
server.Tick();
@@ -150,9 +150,11 @@ namespace BITKit.Net
_timer.Interval = 1000f / TickRate;
_interval = TimeSpan.FromSeconds(1.0 / TickRate);
}
OnStartServer?.Invoke();
server.Start(port);
_timer.Start();
if (ManualTick is false)
_timer.Start();
_isStarted = true;
BIT4Log.Log<KCPNetServer>($"已启动KCP服务器:{port}");
}
@@ -551,14 +553,14 @@ namespace BITKit.Net
{
foreach (var methodInfo in rpcHandle.GetType().GetMethods())
{
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>(true);
if(att is null)continue;
_rpcMethods.TryAdd(methodInfo.Name, methodInfo);
_rpcHandles.TryAdd(methodInfo.Name, rpcHandle);
}
foreach (var eventInfo in rpcHandle.GetType().GetEvents())
{
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>();
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>(true);
if(att is null)continue;
_rpcEvents.TryAdd(eventInfo.Name, eventInfo);