This commit is contained in:
CortexCore 2024-06-12 16:01:56 +08:00
parent 01b19130a9
commit 126131b842
8 changed files with 208 additions and 112 deletions

View File

@ -61,51 +61,53 @@ namespace BITKit
public static object Read(BinaryReader reader)
{
try
if (reader.ReadBoolean())
{
if (reader.ReadBoolean())
var objs = new object[reader.ReadInt32()];
for (var i = 0; i < objs.Length; i++)
{
var objs = new object[reader.ReadInt32()];
for (var i = 0; i < objs.Length; i++)
{
objs[i] = Read(reader);
}
return objs.ToArray();
objs[i] = ReadInternel(reader);
}
}
catch (Exception)
{
}
var typeName = reader.ReadString();
if (netReaders.TryGetValue(typeName, out var netReader))
return netReader.ReadBinaryAsObject(reader);
var instance = System.Activator.CreateInstance(BITSharp.GetTypeFromFullName(typeName));
if (instance is IBinarySerialize serialize)
{
serialize.Read(reader);
return instance;
return objs.ToArray();
}
var json = reader.ReadString();
if (string.IsNullOrEmpty(json))
return ReadInternel(reader);
object ReadInternel(BinaryReader reader)
{
throw new Exception($"从二进制中读取的json值为空");
var typeName = reader.ReadString();
if (netReaders.TryGetValue(typeName, out var netReader))
return netReader.ReadBinaryAsObject(reader);
var instance = System.Activator.CreateInstance(BITSharp.GetTypeFromFullName(typeName));
if (instance is IBinarySerialize serialize)
{
serialize.Read(reader);
return instance;
}
var json = reader.ReadString();
if (string.IsNullOrEmpty(json))
{
throw new Exception($"从二进制中读取的json值为空");
}
try
{
if (BITSharp.TryGetTypeFromFullName(typeName, out var type))
return JsonConvert.DeserializeObject(json, type);
}
catch (Exception e)
{
BIT4Log.Warning<BITBinary>($"反序列化失败,类型:{typeName},值:\n{json}");
BIT4Log.LogException(e);
}
throw new Exception("未找到读取该二进制的BinaryReader");
}
try
{
if (BITSharp.TryGetTypeFromFullName(typeName, out var type))
return JsonConvert.DeserializeObject(json, type);
}
catch (Exception e)
{
BIT4Log.Warning<BITBinary>($"反序列化失败,类型:{typeName},值:\n{json}");
BIT4Log.LogException(e);
}
throw new Exception("未找到读取该二进制的BinaryReader");
}
public static byte[] WriteAsBytes(object value)
@ -119,47 +121,45 @@ namespace BITKit
{
if (value is object[] objects)
{
if (objects.Length is 1)
writer.Write(true);
writer.Write(objects.Length);
foreach (var obj in objects)
{
writer.Write(false);
value = objects[0];
}
else
{
writer.Write(true);
writer.Write(objects.Length);
foreach (var obj in objects)
{
Write(writer,obj);
}
WriteInterel(writer, obj);
}
}
else
{
writer.Write(false);
WriteInterel(writer,value);
}
var typeName = value.GetType().FullName;
writer.Write(typeName!);
if (netReaders.TryGetValue(typeName, out var netReader))
return;
void WriteInterel(BinaryWriter writer, object value)
{
netReader.WriteBinaryAsObject(writer,value);
}
else if (value is IBinarySerialize serialize)
{
serialize.Write(writer);
}
else
{
try
var typeName = value.GetType().FullName;
writer.Write(typeName!);
if (netReaders.TryGetValue(typeName, out var netReader))
{
writer.Write(JsonConvert.SerializeObject(value));
netReader.WriteBinaryAsObject(writer,value);
}
catch (Exception e)
else if (value is IBinarySerialize serialize)
{
BIT4Log.Warning<BITBinary>(typeName);
throw;
serialize.Write(writer);
}
else
{
try
{
writer.Write(JsonConvert.SerializeObject(value));
}
catch (Exception e)
{
BIT4Log.Warning<BITBinary>(typeName);
throw;
}
}
}
}
public static bool IsSupport(object obj) => IsSupport(obj.GetType().FullName);

View File

@ -8,6 +8,7 @@ using Timer = System.Timers.Timer;
using System.Threading.Tasks;
using System.IO;
using System.Numerics;
using System.Reflection;
using BITKit.Net.Examples;
using Newtonsoft.Json;
@ -43,6 +44,9 @@ namespace BITKit.Net
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,object> _rpcHandles = new();
public KcpNetClient()
{
client = new KcpClient(
@ -124,7 +128,18 @@ namespace BITKit.Net
}
}
private async void OnData(ArraySegment<byte> bytes, KcpChannel channel)
private void OnData(ArraySegment<byte> bytes, KcpChannel channel)
{
try
{
OnDataInternel(bytes, channel);
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
}
private async void OnDataInternel(ArraySegment<byte> bytes, KcpChannel channel)
{
using var ms = new MemoryStream(bytes.ToArray());
using var reader = new BinaryReader(ms);
@ -191,19 +206,28 @@ namespace BITKit.Net
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}");
}
using var _ms = new MemoryStream();
using var _writer = new BinaryWriter(_ms);
_writer.Write((byte)NetCommandType.ReturnToServer);
_writer.Write(requestId);
try
{
var value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
object value = null;
if (reader.ReadBoolean())
{
var path = reader.ReadString();
var method = _rpcMethods[path];
var pars = BITBinary.Read(reader).As<object[]>();
value = method.Invoke(_rpcHandles[path],pars);
}
else
{
var commandObj = BITBinary.Read(reader);
var func = _rpc[commandObj.GetType()!.FullName!];
value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
}
_writer.Write(true);
BITBinary.Write(_writer, value);
@ -278,13 +302,22 @@ namespace BITKit.Net
Send(NetCommandType.TargetCommand,id,command);
}
public async UniTask<T> GetFromServer<T>(T command = default)
public async UniTask<T> GetFromServer<T>(string path = default,T command = default)
{
var id = _index++;
using var ms = new MemoryStream();
await using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.GetFromServer);
writer.Write(id);
if (string.IsNullOrEmpty(path))
{
writer.Write(false);
}
else
{
writer.Write(true);
writer.Write(path);
}
BITBinary.Write(writer,command);
var bytes = ms.ToArray();
@ -307,7 +340,7 @@ namespace BITKit.Net
}
}
public UniTask<T> GetFromClient<T>(int id, T command = default)
public UniTask<T> GetFromClient<T>(int id,string path, T command = default)
{
throw new NotImplementedException();
}

View File

@ -10,6 +10,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Threading.Tasks;
using BITKit.Net.Examples;
@ -32,7 +33,8 @@ 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,object> _rpcHandles = new();
public KCPNetServer()
{
@ -148,7 +150,19 @@ namespace BITKit.Net
OnClientDisconnected?.Invoke(Id);
BIT4Log.Log<KCPNetServer>($"{Id}已断开");
}
private async void OnData(int Id, ArraySegment<byte> bytes, KcpChannel channel)
private void OnData(int Id, ArraySegment<byte> bytes, KcpChannel channel)
{
try
{
OnDataInternel(Id, bytes, channel);
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
}
private async void OnDataInternel(int Id, ArraySegment<byte> bytes, KcpChannel channel)
{
using var ms = new MemoryStream(bytes.ToArray());
using var reader = new BinaryReader(ms);
@ -191,37 +205,60 @@ namespace BITKit.Net
case NetCommandType.GetFromServer:
{
var requestId = reader.ReadInt32();
var commandObj = BITBinary.Read(reader);
using var _ms = new MemoryStream();
using var _writer = new BinaryWriter(_ms);
_writer.Write((byte)NetCommandType.ReturnToClient);
_writer.Write(requestId);
using var returnMS = new MemoryStream();
using var returnWriter = new BinaryWriter(returnMS);
returnWriter.Write((byte)NetCommandType.ReturnToClient);
returnWriter.Write(requestId);
try
{
if (_rpc.TryGetValue(commandObj.GetType()!.FullName!, out var func) is false)
if (reader.ReadBoolean())
{
_writer.Write(false);
_writer.Write("未找到对应的Rpc方法");
var path = reader.ReadString();
var pars = BITBinary.Read(reader).As<object[]>();
if (_rpcMethods.TryGetValue(path, out var methodInfo))
{
var value = methodInfo.Invoke(_rpcHandles[path], pars);
returnWriter.Write(true);
BITBinary.Write(returnWriter, value);
}
else
{
returnWriter.Write(false);
returnWriter.Write("未找到对应的Rpc方法");
}
}
else
{
try
var commandObj = BITBinary.Read(reader);
if (_rpc.TryGetValue(commandObj.GetType()!.FullName!, out var func))
{
var value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
_writer.Write(true);
BITBinary.Write(_writer, value);
try
{
var value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
returnWriter.Write(true);
BITBinary.Write(returnWriter, value);
}
catch (Exception e)
{
BIT4Log.LogException(e);
returnWriter.Write(false);
returnWriter.Write(e.Message);
}
}
catch (Exception e)
else
{
BIT4Log.LogException(e);
_writer.Write(false);
_writer.Write(e.Message);
returnWriter.Write(false);
returnWriter.Write("未找到对应的Rpc方法");
}
}
var _bytes = _ms.ToArray();
server.Send(Id, _bytes, KcpChannel.Reliable);
{
var _bytes = returnMS.ToArray();
server.Send(Id, _bytes, KcpChannel.Reliable);
}
}
catch (Exception e)
{
@ -273,18 +310,27 @@ namespace BITKit.Net
Send(id,NetCommandType.Command,command);
}
public UniTask<T> GetFromServer<T>(T command = default)
public UniTask<T> GetFromServer<T>(string path=default,T command = default)
{
throw new NotImplementedException();
}
public async UniTask<T> GetFromClient<T>(int id, T command = default)
public async UniTask<T> GetFromClient<T>(int id,string path=default, T command = default)
{
var index = _index++;
using var ms = new MemoryStream();
await using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.GetFromClient);
writer.Write(index);
if (string.IsNullOrEmpty(path))
{
writer.Write(false);
}
else
{
writer.Write(true);
writer.Write(path);
}
BITBinary.Write(writer,command);
var bytes = ms.ToArray();

View File

@ -4,6 +4,23 @@ namespace BITKit
{
public static class MathO
{
public static T As<T>(this object self) where T : class => self as T;
public static T As<T>(this object self) where T : class
{
{
if (typeof(T) == typeof(object[]))
{
var o = new object[1];
o[0] = self;
return o as T;
}
}
{
if (self is object[] { Length: 1 } o)
{
return o[0] as T;
}
}
return self as T;
}
}
}

View File

@ -74,7 +74,7 @@ namespace BITKit
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
UniTask<T> GetFromServer<T>(T command = default);
UniTask<T> GetFromServer<T>(string path = null,T command = default);
/// <summary>
/// 从客户端获取数据
@ -83,7 +83,7 @@ namespace BITKit
/// <param name="addressablePath">可寻址路劲 e.g. Key</param>
/// <typeparam name="T">远程指令类型</typeparam>
/// <returns></returns>
UniTask<T> GetFromClient<T>(int id,T command = default);
UniTask<T> GetFromClient<T>(int id,string path = null,T command = default);
/// <summary>
/// 添加RPC远程服务服务类型为需要的方法标记[RPC]

View File

@ -89,9 +89,9 @@ namespace BITKit.Net
_netProviderImplementation.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(T command = default)=>_netProviderImplementation.GetFromServer<T>(command);
public UniTask<T> GetFromServer<T>(string path=default,T command = default)=>_netProviderImplementation.GetFromServer<T>(path,command);
public UniTask<T> GetFromClient<T>(int id, T command = default)=>_netProviderImplementation.GetFromClient(id, command);
public UniTask<T> GetFromClient<T>(int id,string path=default, T command = default)=>_netProviderImplementation.GetFromClient(id,path, command);
public void AddRpcHandle(object rpcHandle)
{

View File

@ -96,14 +96,14 @@ namespace BITKit.Net.Kcp
_netProviderImplementation.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(T command = default)
public UniTask<T> GetFromServer<T>(string path=null,T command = default)
{
return _netProviderImplementation.GetFromServer<T>(command);
return _netProviderImplementation.GetFromServer<T>(path,command);
}
public UniTask<T> GetFromClient<T>(int id, T command = default)
public UniTask<T> GetFromClient<T>(int id,string path=null, T command = default)
{
return _netProviderImplementation.GetFromClient<T>(id, command);
return _netProviderImplementation.GetFromClient<T>(id,path, command);
}
public void AddRpcHandle(object rpcHandle)
{
@ -227,7 +227,7 @@ namespace BITKit.Net.Kcp
private async void Hello()
{
BITAppForUnity.ThrowIfNotPlaying();
var value =await GetFromServer(new SimplePing()
var value =await GetFromServer<SimplePing>(null,new SimplePing()
{
StartTime = DateTime.Now
});

View File

@ -113,14 +113,14 @@ namespace BITKit.Net.Kcp
_server.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(T command = default)
public UniTask<T> GetFromServer<T>(string path = null,T command = default)
{
return _serverInstance.GetFromServer(command);
return _serverInstance.GetFromServer(path,command);
}
public UniTask<T> GetFromClient<T>(int id, T command = default)
public UniTask<T> GetFromClient<T>(int id,string path = null, T command = default)
{
return _serverInstance.GetFromClient(id, command);
return _serverInstance.GetFromClient(id,path, command);
}
public void AddRpcHandle(object rpcHandle)
{