This commit is contained in:
parent
01b19130a9
commit
126131b842
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
});
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue