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) 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()]; objs[i] = ReadInternel(reader);
for (var i = 0; i < objs.Length; i++)
{
objs[i] = Read(reader);
}
return objs.ToArray();
} }
}
catch (Exception)
{
}
var typeName = reader.ReadString(); return objs.ToArray();
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(); return ReadInternel(reader);
if (string.IsNullOrEmpty(json))
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) public static byte[] WriteAsBytes(object value)
@ -119,47 +121,45 @@ namespace BITKit
{ {
if (value is object[] objects) 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); WriteInterel(writer, obj);
value = objects[0];
}
else
{
writer.Write(true);
writer.Write(objects.Length);
foreach (var obj in objects)
{
Write(writer,obj);
}
} }
} }
else else
{ {
writer.Write(false); writer.Write(false);
WriteInterel(writer,value);
} }
var typeName = value.GetType().FullName; return;
writer.Write(typeName!); void WriteInterel(BinaryWriter writer, object value)
if (netReaders.TryGetValue(typeName, out var netReader))
{ {
netReader.WriteBinaryAsObject(writer,value); var typeName = value.GetType().FullName;
} writer.Write(typeName!);
else if (value is IBinarySerialize serialize) if (netReaders.TryGetValue(typeName, out var netReader))
{
serialize.Write(writer);
}
else
{
try
{ {
writer.Write(JsonConvert.SerializeObject(value)); netReader.WriteBinaryAsObject(writer,value);
} }
catch (Exception e) else if (value is IBinarySerialize serialize)
{ {
BIT4Log.Warning<BITBinary>(typeName); serialize.Write(writer);
throw;
} }
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); 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.Threading.Tasks;
using System.IO; using System.IO;
using System.Numerics; using System.Numerics;
using System.Reflection;
using BITKit.Net.Examples; using BITKit.Net.Examples;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -43,6 +44,9 @@ namespace BITKit.Net
private int _index = int.MinValue; private int _index = int.MinValue;
private readonly ConcurrentDictionary<int, object> _p2p = new(); private readonly ConcurrentDictionary<int, object> _p2p = new();
private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = 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() public KcpNetClient()
{ {
client = new KcpClient( 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 ms = new MemoryStream(bytes.ToArray());
using var reader = new BinaryReader(ms); using var reader = new BinaryReader(ms);
@ -191,19 +206,28 @@ namespace BITKit.Net
try try
{ {
var requestId = reader.ReadInt32(); 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 _ms = new MemoryStream();
using var _writer = new BinaryWriter(_ms); using var _writer = new BinaryWriter(_ms);
_writer.Write((byte)NetCommandType.ReturnToServer); _writer.Write((byte)NetCommandType.ReturnToServer);
_writer.Write(requestId); _writer.Write(requestId);
try 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); _writer.Write(true);
BITBinary.Write(_writer, value); BITBinary.Write(_writer, value);
@ -278,13 +302,22 @@ namespace BITKit.Net
Send(NetCommandType.TargetCommand,id,command); 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++; var id = _index++;
using var ms = new MemoryStream(); using var ms = new MemoryStream();
await using var writer = new BinaryWriter(ms); await using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.GetFromServer); writer.Write((byte)NetCommandType.GetFromServer);
writer.Write(id); writer.Write(id);
if (string.IsNullOrEmpty(path))
{
writer.Write(false);
}
else
{
writer.Write(true);
writer.Write(path);
}
BITBinary.Write(writer,command); BITBinary.Write(writer,command);
var bytes = ms.ToArray(); 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(); throw new NotImplementedException();
} }

View File

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

View File

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

View File

@ -89,9 +89,9 @@ namespace BITKit.Net
_netProviderImplementation.ClientCommand(id, command); _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) public void AddRpcHandle(object rpcHandle)
{ {

View File

@ -96,14 +96,14 @@ namespace BITKit.Net.Kcp
_netProviderImplementation.ClientCommand(id, command); _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) public void AddRpcHandle(object rpcHandle)
{ {
@ -227,7 +227,7 @@ namespace BITKit.Net.Kcp
private async void Hello() private async void Hello()
{ {
BITAppForUnity.ThrowIfNotPlaying(); BITAppForUnity.ThrowIfNotPlaying();
var value =await GetFromServer(new SimplePing() var value =await GetFromServer<SimplePing>(null,new SimplePing()
{ {
StartTime = DateTime.Now StartTime = DateTime.Now
}); });

View File

@ -113,14 +113,14 @@ namespace BITKit.Net.Kcp
_server.ClientCommand(id, command); _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) public void AddRpcHandle(object rpcHandle)
{ {