1
This commit is contained in:
@@ -18,6 +18,7 @@ namespace BITKit.Net
|
||||
{
|
||||
public class KCPNetServer:INetServer,INetProvider
|
||||
{
|
||||
public string Name { get; set; } = "Default";
|
||||
public int TickRate { get; set; } = 16;
|
||||
public bool ManualTick { get; set; }
|
||||
public event Action<int> OnClientConnected;
|
||||
@@ -36,12 +37,15 @@ namespace BITKit.Net
|
||||
private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = new();
|
||||
private readonly ConcurrentDictionary<string,MethodInfo> _rpcMethods = 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 DateTime _now=DateTime.Now;
|
||||
private TimeSpan _interval=TimeSpan.FromSeconds(0.32);
|
||||
|
||||
private byte[] _heartBeat = new byte[] { (byte)NetCommandType.Heartbeat };
|
||||
|
||||
public KCPNetServer()
|
||||
{
|
||||
server = new KcpServer(
|
||||
@@ -70,21 +74,35 @@ namespace BITKit.Net
|
||||
_now = DateTime.UtcNow;
|
||||
try
|
||||
{
|
||||
foreach (var id in Connections.Keys.ToArray())
|
||||
{
|
||||
server.Send(id,_heartBeat , KcpChannel.Unreliable);
|
||||
if (!_lastHeartbeat.TryGetValue(id, out var time)) continue;
|
||||
if (!((_now - time).TotalSeconds > 1)) continue;
|
||||
server.Disconnect(id);
|
||||
_lastHeartbeat.TryRemove(id);
|
||||
BIT4Log.Log<KCPNetServer>($"{Name}:链接{id}超时,已断开");
|
||||
}
|
||||
|
||||
if (server.IsActive() is false || ManualTick) return;
|
||||
|
||||
server.Tick();
|
||||
|
||||
|
||||
//BIT4Log.Log<KCPNetServer>($"{Name}目前有{server.connections.Count}个链接");
|
||||
|
||||
while (_sendQueue.TryDequeue(out var value))
|
||||
{
|
||||
|
||||
if (server.connections.ContainsKey(value.id))
|
||||
{
|
||||
server.Send(value.id,value.bytes,KcpChannel.Reliable);
|
||||
server.Send(value.id, value.bytes, KcpChannel.Reliable);
|
||||
}
|
||||
else
|
||||
{
|
||||
BIT4Log.Log<KCPNetServer>($"链接{value.id}已丢失,丢弃了{value.bytes.Length}个字节");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (server.IsActive() is false || ManualTick) return;
|
||||
server.Tick();
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
@@ -103,8 +121,8 @@ namespace BITKit.Net
|
||||
if (TickRate > 0)
|
||||
{
|
||||
_timer.Interval = 1000f / TickRate;
|
||||
_interval = TimeSpan.FromSeconds(1.0 / TickRate);
|
||||
}
|
||||
_interval = TimeSpan.FromSeconds(1.0 / TickRate);
|
||||
OnStartServer?.Invoke();
|
||||
server.Start(port);
|
||||
_timer.Start();
|
||||
@@ -154,12 +172,11 @@ namespace BITKit.Net
|
||||
));
|
||||
|
||||
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
try
|
||||
{
|
||||
server.Tick();
|
||||
Tick(null,null);
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
@@ -169,23 +186,33 @@ namespace BITKit.Net
|
||||
|
||||
public void HandShake()
|
||||
{
|
||||
foreach (var Id in server.connections.Keys)
|
||||
foreach (var id in server.connections.Keys)
|
||||
{
|
||||
server.Send(Id, new byte[]{0x03, 0x04}, KcpChannel.Reliable);
|
||||
server.Send(id, new byte[]{0x03, 0x04}, KcpChannel.Reliable);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnConnectedInternel(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 OnConnected(int Id)
|
||||
{
|
||||
OnClientConnected?.Invoke(Id);
|
||||
ClientCommand(Id,new NetClientAllocateIdCommand
|
||||
{
|
||||
Id = Id,
|
||||
Ip = server.connections[Id].remoteEndPoint.ToString()
|
||||
});
|
||||
BIT4Log.Log<KCPNetServer>($"{Id}已加入");
|
||||
SendMessageToClient(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)
|
||||
{
|
||||
@@ -229,8 +256,20 @@ namespace BITKit.Net
|
||||
_events.InvokeDirect(command.GetType().FullName, tuple);
|
||||
break;
|
||||
case NetCommandType.Heartbeat:
|
||||
_sendQueue.Enqueue((Id,new byte[] { (byte)NetCommandType.Heartbeat }));
|
||||
if (Connections.ContainsKey(Id))
|
||||
{
|
||||
_lastHeartbeat.AddOrUpdate(Id,OnAdd,OnUpdate);
|
||||
}
|
||||
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())
|
||||
{
|
||||
@@ -354,6 +393,9 @@ namespace BITKit.Net
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void OnError(int Id, ErrorCode errorCode, string message)
|
||||
{
|
||||
BIT4Log.Log<KCPNetServer>($"异常:{errorCode},{message}");
|
||||
@@ -374,7 +416,11 @@ namespace BITKit.Net
|
||||
|
||||
public void ClientCommand<T>(int id, T command)
|
||||
{
|
||||
Send(id,NetCommandType.Command,command);
|
||||
using var ms = new MemoryStream();
|
||||
using var writer = new BinaryWriter(ms);
|
||||
writer.Write((byte)NetCommandType.Command);
|
||||
BITBinary.Write(writer,command);
|
||||
_sendQueue.Enqueue((id,ms.ToArray()));
|
||||
}
|
||||
|
||||
public UniTask<T> GetFromServer<T>(string path=default,params object[] pars)
|
||||
@@ -386,8 +432,8 @@ namespace BITKit.Net
|
||||
{
|
||||
await UniTask.SwitchToThreadPool();
|
||||
var index = _index++;
|
||||
using var ms = new MemoryStream();
|
||||
await using var writer = new BinaryWriter(ms);
|
||||
var ms = new MemoryStream();
|
||||
var writer = new BinaryWriter(ms);
|
||||
writer.Write((byte)NetCommandType.GetFromClient);
|
||||
writer.Write(index);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
@@ -402,17 +448,21 @@ namespace BITKit.Net
|
||||
BITBinary.Write(writer,pars);
|
||||
|
||||
var bytes = ms.ToArray();
|
||||
//server.Send(id,bytes,KcpChannel.Reliable);
|
||||
|
||||
await ms.DisposeAsync();
|
||||
await writer.DisposeAsync();
|
||||
|
||||
_sendQueue.Enqueue((id,bytes));
|
||||
var startTime = _now;
|
||||
while (true)
|
||||
{
|
||||
if((_now-startTime).TotalSeconds>5)
|
||||
throw new TimeoutException($"等待超时,Id:{id},时间{DateTime.Now-startTime}");
|
||||
var time = _now - startTime;
|
||||
if(time.TotalSeconds>5)
|
||||
throw new TimeoutException($"等待超时,Id:{id},时间{time.TotalSeconds}");
|
||||
|
||||
if (_p2p.TryRemove(index, out var value))
|
||||
{
|
||||
await BITApp.SwitchToMainThread();
|
||||
//await BITApp.SwitchToMainThread();
|
||||
if (value is Exception e)
|
||||
{
|
||||
throw e;
|
||||
@@ -507,28 +557,32 @@ namespace BITKit.Net
|
||||
|
||||
public void SendRT(string rpcName, params object[] pars)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
throw new NotImplementedException("服务端不支持此方法");
|
||||
}
|
||||
|
||||
public void SendTargetRT(int id, string rpcName, params object[] pars)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var ms = new MemoryStream();
|
||||
using var writer = new BinaryWriter(ms);
|
||||
writer.Write((byte)NetCommandType.TargetRpc);
|
||||
writer.Write(rpcName);
|
||||
BITBinary.Write(writer,pars);
|
||||
var bytes = ms.ToArray();
|
||||
_sendQueue.Enqueue((id,bytes));
|
||||
}
|
||||
|
||||
public void SendAllRT(string rpcName, params object[] pars)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
private void Send(int id,NetCommandType commandType,params object[] values)
|
||||
{
|
||||
var bytes = BinaryBuilder
|
||||
.Create()
|
||||
.Write((byte)commandType)
|
||||
.WriteObject(values)
|
||||
.Build();
|
||||
//server.Send(id,bytes, KcpChannel.Reliable);
|
||||
using var ms = new MemoryStream();
|
||||
using var writer = new BinaryWriter(ms);
|
||||
writer.Write((byte)NetCommandType.AllRpc);
|
||||
writer.Write(rpcName);
|
||||
BITBinary.Write(writer,pars);
|
||||
var bytes = ms.ToArray();
|
||||
foreach (var id in server.connections.Keys)
|
||||
{
|
||||
_sendQueue.Enqueue((id,bytes));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user