This commit is contained in:
CortexCore 2024-06-08 15:12:48 +08:00
parent b9731c20a1
commit 3e8bd54a08
9 changed files with 155 additions and 182 deletions

View File

@ -40,9 +40,9 @@ namespace BITKit.Net
private readonly ValidHandle _isConnected = new(); private readonly ValidHandle _isConnected = new();
private int _index = 1001; private int _index = int.MinValue;
private readonly ConcurrentDictionary<int, object> _p2p = new(); private readonly ConcurrentDictionary<int, object> _p2p = new();
private readonly ConcurrentDictionary<string,object> _rpc = new(); private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = new();
public KcpNetClient() public KcpNetClient()
{ {
client = new KcpClient( client = new KcpClient(
@ -168,8 +168,42 @@ namespace BITKit.Net
break; break;
case NetCommandType.ReturnToClient: case NetCommandType.ReturnToClient:
var id = reader.ReadInt32(); var id = reader.ReadInt32();
var value = BITBinary.Read(reader); try
_p2p.TryAdd(id,value); {
var value = BITBinary.Read(reader);
_p2p.TryAdd(id,value);
}
catch (Exception e)
{
BIT4Log.Warning<INetClient>($"请求返回失败:{id}");
BIT4Log.LogException(e);
}
break;
case NetCommandType.GetFromClient:
try
{
var requestId = reader.ReadInt32();
var commandObj = BITBinary.Read(reader);
if (_rpc.TryGetValue(commandObj.GetType().FullName, out var func) is false)
{
throw new NotImplementedException($"未找到对应的方法:{commandObj.GetType().FullName}");
}
var value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
using var _ms = new MemoryStream();
using var _writer = new BinaryWriter(_ms);
_writer.Write((byte)NetCommandType.ReturnToServer);
_writer.Write(requestId);
BITBinary.Write(_writer, value);
var _bytes = _ms.ToArray();
commandQueue.Enqueue(_bytes);
}
catch(Exception e)
{
BIT4Log.LogException(e);
}
break; break;
default: default:
BIT4Log.Log<KcpClient>($"未知消息类型:{type},字节:{(byte)type}"); BIT4Log.Log<KcpClient>($"未知消息类型:{type},字节:{(byte)type}");
@ -268,12 +302,18 @@ namespace BITKit.Net
_events.AddListener<T>(handle); _events.AddListener<T>(handle);
} }
public void AddCommandListener<T>(Func<T, T> func) public void AddCommandListener<T>(Func<T,UniTask<T>> func)
{ {
_rpc.GetOrAdd(typeof(T).FullName, func); _rpc.TryAdd(typeof(T).FullName, F);
return;
async UniTask<object> F(object o)
{
return await func.Invoke((T)o);
}
} }
public void RemoveCommandListener<T>(Func<T, T> func) public void RemoveCommandListener<T>(Func<T,UniTask<T>> func)
{ {
_rpc.TryRemove(typeof(T).FullName, out _); _rpc.TryRemove(typeof(T).FullName, out _);
} }

View File

@ -9,6 +9,8 @@ using Timer = System.Timers.Timer;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using BITKit.Net.Examples; using BITKit.Net.Examples;
namespace BITKit.Net namespace BITKit.Net
@ -29,7 +31,7 @@ namespace BITKit.Net
private int _index = 1001; private int _index = 1001;
private readonly ConcurrentDictionary<int, object> _p2p = new(); private readonly ConcurrentDictionary<int, object> _p2p = new();
private readonly ConcurrentDictionary<string,Func<object,object>> _rpc = new(); private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = new();
public KCPNetServer() public KCPNetServer()
@ -44,11 +46,13 @@ namespace BITKit.Net
_timer.Elapsed += Tick; _timer.Elapsed += Tick;
BIT4Log.Log<KCPNetServer>("已创建KCP服务器"); BIT4Log.Log<KCPNetServer>("已创建KCP服务器");
AddCommandListener<SimplePing>(x => AddCommandListener<SimplePing>(F);
return;
UniTask<SimplePing> F(SimplePing p)
{ {
x.EndTime = DateTime.Now; p.EndTime = DateTime.Now;
return x; return UniTask.FromResult(p);
}); }
} }
private void Tick(object sender, ElapsedEventArgs e) private void Tick(object sender, ElapsedEventArgs e)
@ -107,7 +111,18 @@ namespace BITKit.Net
public void Tick() => server.Tick(); public void Tick()
{
try
{
server.Tick();
}
catch (SocketException)
{
BIT4Log.Log<INetServer>("有用户断开连接,如有异常请检查");
}
}
public void HandShake() public void HandShake()
{ {
foreach (var Id in server.connections.Keys) foreach (var Id in server.connections.Keys)
@ -133,7 +148,7 @@ namespace BITKit.Net
OnClientDisconnected?.Invoke(Id); OnClientDisconnected?.Invoke(Id);
BIT4Log.Log<KCPNetServer>($"{Id}已断开"); BIT4Log.Log<KCPNetServer>($"{Id}已断开");
} }
private void OnData(int Id, ArraySegment<byte> bytes, KcpChannel channel) private async void OnData(int Id, ArraySegment<byte> bytes, KcpChannel channel)
{ {
using var ms = new MemoryStream(bytes.ToArray()); using var ms = new MemoryStream(bytes.ToArray());
using var reader = new BinaryReader(ms); using var reader = new BinaryReader(ms);
@ -179,15 +194,12 @@ namespace BITKit.Net
var requestId = reader.ReadInt32(); var requestId = reader.ReadInt32();
var commandObj = BITBinary.Read(reader); var commandObj = BITBinary.Read(reader);
BIT4Log.Log<KCPNetServer>($"已收到请求:{commandObj},请求ID:{requestId}");
if (_rpc.TryGetValue(commandObj.GetType().FullName, out var func) is false) if (_rpc.TryGetValue(commandObj.GetType().FullName, out var func) is false)
{ {
throw new NotImplementedException($"未找到对应的方法:{commandObj.GetType().FullName}"); throw new NotImplementedException($"未找到对应的方法:{commandObj.GetType().FullName}");
} }
var value = func.As<Func<object,object>>().Invoke(commandObj); var value =await func.As<Func<object,UniTask<object>>>().Invoke(commandObj);
using var _ms = new MemoryStream(); using var _ms = new MemoryStream();
using var _writer = new BinaryWriter(_ms); using var _writer = new BinaryWriter(_ms);
_writer.Write((byte)NetCommandType.ReturnToClient); _writer.Write((byte)NetCommandType.ReturnToClient);
@ -202,6 +214,13 @@ namespace BITKit.Net
Send(Id,NetCommandType.ReturnToClient,-1,0); Send(Id,NetCommandType.ReturnToClient,-1,0);
} }
break; break;
case NetCommandType.ReturnToServer:
{
var id = reader.ReadInt32();
var value = BITBinary.Read(reader);
_p2p.TryAdd(id, value);
}
break;
default: default:
BIT4Log.Log<KCPNetServer>($"未知消息类型:{type},字节:{(byte)type}"); BIT4Log.Log<KCPNetServer>($"未知消息类型:{type},字节:{(byte)type}");
BIT4Log.Log<KCPNetServer>($"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})"); BIT4Log.Log<KCPNetServer>($"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
@ -236,9 +255,29 @@ namespace BITKit.Net
throw new NotImplementedException(); throw new NotImplementedException();
} }
public UniTask<T> GetFromClient<T>(int id, T command = default) public async UniTask<T> GetFromClient<T>(int id, T command = default)
{ {
throw new NotImplementedException(); var index = _index++;
using var ms = new MemoryStream();
await using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.GetFromClient);
writer.Write(index);
BITBinary.Write(writer,command);
var bytes = ms.ToArray();
server.Send(id,bytes,KcpChannel.Reliable);
var startTime = DateTime.Now;
while (true)
{
if(DateTime.Now-startTime>TimeSpan.FromSeconds(5) || server.connections.ContainsKey(id) is false)
throw new TimeoutException();
if (_p2p.TryRemove(index, out var value))
{
return (T)value;
}
await Task.Delay(100);
}
} }
public void AddRpcHandle(object rpcHandle) public void AddRpcHandle(object rpcHandle)
@ -251,17 +290,17 @@ namespace BITKit.Net
_events.AddListener<T>(handle); _events.AddListener<T>(handle);
} }
public void AddCommandListener<T>(Func<T, T> func) public void AddCommandListener<T>(Func<T,UniTask<T>> func)
{ {
_rpc.TryAdd(typeof(T).FullName, F); _rpc.TryAdd(typeof(T).FullName, F);
return; return;
object F(object o) async UniTask<object> F(object o)
{ {
return func.Invoke((T)o); return await func.Invoke((T)o);
} }
} }
public void RemoveCommandListener<T>(Func<T, T> func) public void RemoveCommandListener<T>(Func<T,UniTask<T>> func)
{ {
_rpc.TryRemove(typeof(T).FullName, out _); _rpc.TryRemove(typeof(T).FullName, out _);
} }
@ -283,6 +322,11 @@ namespace BITKit.Net
} }
} }
public void KickClient(int id)
{
server.Disconnect(id);
}
public void RemoveCommandListener<T>(Action<T> handle) public void RemoveCommandListener<T>(Action<T> handle)
{ {
_events.RemoveListener<T>(handle); _events.RemoveListener<T>(handle);

View File

@ -97,19 +97,26 @@ namespace BITKit
/// <param name="handle">远程指令回调</param> /// <param name="handle">远程指令回调</param>
/// <typeparam name="T">远程指令类型</typeparam> /// <typeparam name="T">远程指令类型</typeparam>
void AddCommandListener<T>(Action<T> handle); void AddCommandListener<T>(Action<T> handle);
/// <summary>
/// 取消监听远程指令
/// </summary>
/// <param name="handle"></param>
/// <typeparam name="T"></typeparam>
void RemoveCommandListener<T>(Action<T> handle);
/// <summary> /// <summary>
/// 监听远程func /// 监听远程func
/// </summary> /// </summary>
/// <param name="func"></param> /// <param name="func"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
void AddCommandListener<T>(Func<T,T> func); void AddCommandListener<T>(Func<T,UniTask<T>> func);
/// <summary> /// <summary>
/// 取消监听远程指令 /// 取消监听远程指令
/// </summary> /// </summary>
/// <param name="handle">远程指令回调</param> /// <param name="handle">远程指令回调</param>
/// <typeparam name="T">远程指令类型</typeparam> /// <typeparam name="T">远程指令类型</typeparam>
void RemoveCommandListener<T>(Func<T,T> func); void RemoveCommandListener<T>(Func<T,UniTask<T>> func);
/// <summary> /// <summary>
/// 向服务端发送Rpc /// 向服务端发送Rpc
@ -215,6 +222,11 @@ namespace BITKit
/// <param name="handle"></param> /// <param name="handle"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
void AddCommandListenerWithId<T>(Action<int,T> handle); void AddCommandListenerWithId<T>(Action<int,T> handle);
/// <summary>
/// 踢出客户端
/// </summary>
/// <param name="id"></param>
void KickClient(int id);
} }
/// <summary> /// <summary>
/// 基本网络客户端的接口定义,包括了基本客户端的功能 /// 基本网络客户端的接口定义,包括了基本客户端的功能

View File

@ -8,7 +8,8 @@
"GUID:49b49c76ee64f6b41bf28ef951cb0e50", "GUID:49b49c76ee64f6b41bf28ef951cb0e50",
"GUID:9354affc93e0f3e4a904785e7d4c0f59", "GUID:9354affc93e0f3e4a904785e7d4c0f59",
"GUID:c56f2ae4d67b9b947a600c84225206a2", "GUID:c56f2ae4d67b9b947a600c84225206a2",
"GUID:296866320aab85a42a0403bf684bac59" "GUID:296866320aab85a42a0403bf684bac59",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

@ -103,14 +103,19 @@ namespace BITKit.Net
_netProviderImplementation.AddCommandListener(handle); _netProviderImplementation.AddCommandListener(handle);
} }
public void AddCommandListener<T>(Func<T, T> func) public void RemoveCommandListener<T>(Action<T> handle)
{ {
throw new NotImplementedException(); _netProviderImplementation.RemoveCommandListener(handle);
} }
public void RemoveCommandListener<T>(Func<T, T> func) public void AddCommandListener<T>(Func<T, UniTask<T>> func)
{ {
throw new NotImplementedException(); _netProviderImplementation.AddCommandListener(func);
}
public void RemoveCommandListener<T>(Func<T, UniTask<T>> func)
{
_netProviderImplementation.RemoveCommandListener(func);
} }
public void SendRT(string rpcName, params object[] pars) public void SendRT(string rpcName, params object[] pars)
{ {
@ -189,6 +194,11 @@ namespace BITKit.Net
{ {
_netServerImplementation1.AddCommandListenerWithId(handle); _netServerImplementation1.AddCommandListenerWithId(handle);
} }
public void KickClient(int id)
{
_netServerImplementation1.KickClient(id);
}
} }
public class GameNetProvider : MonoBehaviour public class GameNetProvider : MonoBehaviour

View File

@ -115,14 +115,19 @@ namespace BITKit.Net.Kcp
_netProviderImplementation.AddCommandListener(handle); _netProviderImplementation.AddCommandListener(handle);
} }
public void AddCommandListener<T>(Func<T, T> func) public void RemoveCommandListener<T>(Action<T> handle)
{ {
throw new NotImplementedException(); _netProviderImplementation.RemoveCommandListener(handle);
} }
public void RemoveCommandListener<T>(Func<T, T> func) public void AddCommandListener<T>(Func<T, UniTask<T>> func)
{ {
throw new NotImplementedException(); _netProviderImplementation.AddCommandListener(func);
}
public void RemoveCommandListener<T>(Func<T, UniTask<T>> func)
{
_netProviderImplementation.RemoveCommandListener(func);
} }
public void SendRT(string rpcName, params object[] pars) public void SendRT(string rpcName, params object[] pars)
{ {

View File

@ -1,133 +0,0 @@
using System;
using Cysharp.Threading.Tasks;
namespace BITKit.Net.Kcp
{
[Serializable]
public class MonoKcpClientSingleton : INetProvider,INetClient
{
private bool _manualTick;
private INetClient _netClientImplementation => MonoKcpClient.Singleton;
private INetProvider _netProviderImplementation => MonoKcpClient.Singleton;
public event Action OnStartConnect
{
add => _netClientImplementation.OnStartConnect += value;
remove => _netClientImplementation.OnStartConnect -= value;
}
public event Action OnConnected
{
add => _netClientImplementation.OnConnected += value;
remove => _netClientImplementation.OnConnected -= value;
}
public event Action OnDisconnected
{
add => _netClientImplementation.OnDisconnected += value;
remove => _netClientImplementation.OnDisconnected -= value;
}
public event Action OnConnectedFailed
{
add => _netClientImplementation.OnConnectedFailed += value;
remove => _netClientImplementation.OnConnectedFailed -= value;
}
public bool IsConnected => _netClientImplementation.IsConnected;
public bool ManualTick
{
get => _netClientImplementation.ManualTick;
set => _netClientImplementation.ManualTick = value;
}
public int Ping => _netClientImplementation.Ping;
public int Id => _netClientImplementation.Id;
public void Disconnect()
{
_netClientImplementation.Disconnect();
}
public UniTask<bool> Connect(string address = "localhost", ushort port = 27014)
{
return _netClientImplementation.Connect(address, port);
}
public void SendServerMessage(string message)
{
_netClientImplementation.SendServerMessage(message);
}
public void ServerCommand<T>(T command = default)
{
_netProviderImplementation.ServerCommand(command);
}
public void AllClientCommand<T>(T command = default)
{
_netProviderImplementation.AllClientCommand(command);
}
public void ClientCommand<T>(int id, T command)
{
_netProviderImplementation.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(T command = default)
{
return _netProviderImplementation.GetFromServer<T>(command);
}
public UniTask<T> GetFromClient<T>(int id, T command = default)
{
return _netProviderImplementation.GetFromClient<T>(id, command);
}
public void AddRpcHandle(object rpcHandle)
{
_netProviderImplementation.AddRpcHandle(rpcHandle);
}
public void AddCommandListener<T>(Action<T> handle)
{
_netProviderImplementation.AddCommandListener(handle);
}
public void AddCommandListener<T>(Func<T, T> func)
{
throw new NotImplementedException();
}
public void RemoveCommandListener<T>(Func<T, T> func)
{
throw new NotImplementedException();
}
public void SendRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendRT(rpcName, pars);
}
public void SendTargetRT(int id, string rpcName, params object[] pars)
{
_netProviderImplementation.SendTargetRT(id, rpcName, pars);
}
public void SendAllRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendAllRT(rpcName, pars);
}
public void Tick()
{
_netProviderImplementation.Tick();
}
public void HandShake()
{
_netProviderImplementation.HandShake();
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 85f2774aa6284284686cd562b03c654b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -74,7 +74,12 @@ namespace BITKit.Net.Kcp
{ {
_netServerImplementation.AddCommandListenerWithId(handle); _netServerImplementation.AddCommandListenerWithId(handle);
} }
public void KickClient(int id)
{
_netServerImplementation.KickClient(id);
}
[BIT] [BIT]
private void EditorStartServer() private void EditorStartServer()
{ {
@ -127,12 +132,12 @@ namespace BITKit.Net.Kcp
_server.AddCommandListener(handle); _server.AddCommandListener(handle);
} }
public void AddCommandListener<T>(Func<T, T> func) public void AddCommandListener<T>(Func<T,UniTask<T>> func)
{ {
_serverInstance.AddCommandListener(func); _serverInstance.AddCommandListener(func);
} }
public void RemoveCommandListener<T>(Func<T, T> func) public void RemoveCommandListener<T>(Func<T,UniTask<T>> func)
{ {
_serverInstance.RemoveCommandListener(func); _serverInstance.RemoveCommandListener(func);
} }