This commit is contained in:
parent
d3fd104900
commit
a0d95098b8
|
@ -3,6 +3,7 @@
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
#endif
|
#endif
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -61,15 +62,22 @@ namespace BITKit
|
||||||
|
|
||||||
public static object Read(BinaryReader reader)
|
public static object Read(BinaryReader reader)
|
||||||
{
|
{
|
||||||
|
// 检测是否为数组
|
||||||
if (reader.ReadBoolean())
|
if (reader.ReadBoolean())
|
||||||
{
|
{
|
||||||
var objs = new object[reader.ReadInt32()];
|
//读取数组类型的名称
|
||||||
for (var i = 0; i < objs.Length; i++)
|
var arrayTypeName = reader.ReadString();
|
||||||
|
//获取数组类型
|
||||||
|
var arrayType = BITSharp.GetTypeFromFullName(arrayTypeName);
|
||||||
|
//创建数组实例
|
||||||
|
var array = Array.CreateInstance(arrayType, reader.ReadInt32());
|
||||||
|
//循环Reader
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
{
|
{
|
||||||
objs[i] = ReadInternel(reader);
|
//设置值
|
||||||
|
array.SetValue(ReadInternel(reader),i);
|
||||||
}
|
}
|
||||||
|
return array;
|
||||||
return objs.ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReadInternel(reader);
|
return ReadInternel(reader);
|
||||||
|
@ -82,7 +90,18 @@ namespace BITKit
|
||||||
if (netReaders.TryGetValue(typeName, out var netReader))
|
if (netReaders.TryGetValue(typeName, out var netReader))
|
||||||
return netReader.ReadBinaryAsObject(reader);
|
return netReader.ReadBinaryAsObject(reader);
|
||||||
|
|
||||||
var instance = System.Activator.CreateInstance(BITSharp.GetTypeFromFullName(typeName));
|
var type = BITSharp.GetTypeFromFullName(typeName);
|
||||||
|
|
||||||
|
object instance = null;
|
||||||
|
if (type.IsArray)
|
||||||
|
{
|
||||||
|
instance = Array.CreateInstance(type.GetElementType()!, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instance = System.Activator.CreateInstance(type);
|
||||||
|
}
|
||||||
|
|
||||||
if (instance is IBinarySerialize serialize)
|
if (instance is IBinarySerialize serialize)
|
||||||
{
|
{
|
||||||
serialize.Read(reader);
|
serialize.Read(reader);
|
||||||
|
@ -97,7 +116,7 @@ namespace BITKit
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (BITSharp.TryGetTypeFromFullName(typeName, out var type))
|
if (BITSharp.TryGetTypeFromFullName(typeName, out type))
|
||||||
return JsonConvert.DeserializeObject(json, type);
|
return JsonConvert.DeserializeObject(json, type);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -119,11 +138,13 @@ namespace BITKit
|
||||||
}
|
}
|
||||||
public static void Write(BinaryWriter writer, object value)
|
public static void Write(BinaryWriter writer, object value)
|
||||||
{
|
{
|
||||||
if (value is object[] objects)
|
if (value is IEnumerable enumerable)
|
||||||
{
|
{
|
||||||
|
var pars = enumerable.Cast<object>().ToArray();
|
||||||
writer.Write(true);
|
writer.Write(true);
|
||||||
writer.Write(objects.Length);
|
writer.Write(value.GetType().GetElementType()!.FullName!);
|
||||||
foreach (var obj in objects)
|
writer.Write(pars.Count());
|
||||||
|
foreach (var obj in pars)
|
||||||
{
|
{
|
||||||
WriteInterel(writer, obj);
|
WriteInterel(writer, obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 39a2cf28bc8a59c4ab975f015c66d39d
|
guid: fe988b178709928459e7b3ec5849dcfa
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
|
|
|
@ -7,8 +7,8 @@ namespace BITKit.Net
|
||||||
public static readonly KcpConfig Config = new KcpConfig(
|
public static readonly KcpConfig Config = new KcpConfig(
|
||||||
NoDelay: true,
|
NoDelay: true,
|
||||||
DualMode: false,
|
DualMode: false,
|
||||||
Interval: 200, // 1ms so at interval code at least runs.
|
Interval: 1, // 1ms so at interval code at least runs.
|
||||||
Timeout: 2000,
|
Timeout: 8000,
|
||||||
CongestionWindow: false
|
CongestionWindow: false
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace BITKit.Net
|
||||||
public int Id { get; private set; } = -1;
|
public int Id { get; private set; } = -1;
|
||||||
private readonly KcpClient client;
|
private readonly KcpClient client;
|
||||||
|
|
||||||
private readonly Queue<byte[]> commandQueue = new();
|
private readonly ConcurrentQueue<byte[]> _commandQueue = new();
|
||||||
|
|
||||||
private DateTime _lastPingTime = DateTime.Now;
|
private DateTime _lastPingTime = DateTime.Now;
|
||||||
|
|
||||||
|
@ -92,6 +92,7 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
client.Disconnect();
|
client.Disconnect();
|
||||||
_isConnected.RemoveElement(this);
|
_isConnected.RemoveElement(this);
|
||||||
|
_timer.Stop();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext,BITApp.CancellationToken);
|
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext,BITApp.CancellationToken);
|
||||||
|
@ -108,30 +109,35 @@ namespace BITKit.Net
|
||||||
await UniTask.SwitchToThreadPool();
|
await UniTask.SwitchToThreadPool();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_lastHeartbeat = DateTime.Now;
|
||||||
client.Connect(address, port);
|
client.Connect(address, port);
|
||||||
for (var i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
client.Tick();
|
|
||||||
await Task.Delay(100);
|
|
||||||
}
|
|
||||||
_timer.Start();
|
_timer.Start();
|
||||||
Traffic+=new float2(1,0);
|
// for (var i = 0; i < 5; i++)
|
||||||
client.Send(new[] { (byte)NetCommandType.Heartbeat }, KcpChannel.Reliable);
|
// {
|
||||||
|
// client.Tick();
|
||||||
|
// await Task.Delay(100);
|
||||||
|
// }
|
||||||
|
|
||||||
|
_commandQueue.Enqueue(new []{(byte)NetCommandType.Heartbeat });
|
||||||
|
|
||||||
if (BITApp.SynchronizationContext is not null)
|
if (BITApp.SynchronizationContext is not null)
|
||||||
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
||||||
if (client.connected)
|
if (client.connected)
|
||||||
{
|
{
|
||||||
SendServerMessage(Environment.MachineName);
|
SendServerMessage(Environment.MachineName);
|
||||||
|
Traffic+=new float2(1,0);
|
||||||
|
_commandQueue.Enqueue(new []{(byte)NetCommandType.Heartbeat});
|
||||||
}
|
}
|
||||||
for (var i = 0; i < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
client.Tick();
|
client.Tick();
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client.connected is false)
|
if (client.connected is false)
|
||||||
{
|
{
|
||||||
OnConnectedFailed?.Invoke();
|
OnConnectedFailed?.Invoke();
|
||||||
|
Disconnect();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return client.connected;
|
return client.connected;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +147,7 @@ namespace BITKit.Net
|
||||||
if (BITApp.SynchronizationContext is not null)
|
if (BITApp.SynchronizationContext is not null)
|
||||||
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
||||||
OnConnectedFailed?.Invoke();
|
OnConnectedFailed?.Invoke();
|
||||||
|
_timer.Stop();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,8 +198,7 @@ namespace BITKit.Net
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case NetCommandType.Heartbeat:
|
case NetCommandType.Heartbeat:
|
||||||
Traffic+=new float2(1,0);
|
_commandQueue.Enqueue(new []{(byte)NetCommandType.Heartbeat });
|
||||||
client.Send(new[] { (byte)NetCommandType.Heartbeat }, KcpChannel.Reliable);
|
|
||||||
_isConnected.AddElement(this);
|
_isConnected.AddElement(this);
|
||||||
_lastHeartbeat = DateTime.Now;
|
_lastHeartbeat = DateTime.Now;
|
||||||
break;
|
break;
|
||||||
|
@ -282,7 +288,8 @@ namespace BITKit.Net
|
||||||
returnWriter.Write(e.Message);
|
returnWriter.Write(e.Message);
|
||||||
}
|
}
|
||||||
var _bytes = returnMS.ToArray();
|
var _bytes = returnMS.ToArray();
|
||||||
commandQueue.Enqueue(_bytes);
|
|
||||||
|
_commandQueue.Enqueue(_bytes);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
@ -300,29 +307,16 @@ namespace BITKit.Net
|
||||||
|
|
||||||
private async void OnConnectedInternal()
|
private async void OnConnectedInternal()
|
||||||
{
|
{
|
||||||
if (BITApp.SynchronizationContext is not null)
|
// if (BITApp.SynchronizationContext is not null)
|
||||||
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
// await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
||||||
OnConnected?.Invoke();
|
// OnConnected?.Invoke();
|
||||||
BIT4Log.Log<KcpNetClient>("已连接");
|
// BIT4Log.Log<KcpNetClient>("已连接");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnDisconnectInternal()
|
private async void OnDisconnectInternal()
|
||||||
{
|
{
|
||||||
//BIT4Log.Log<KcpNetClient>("断开连接");
|
BIT4Log.Log<KcpNetClient>("连接被断开");
|
||||||
_timer.Stop();
|
Disconnect();
|
||||||
try
|
|
||||||
{
|
|
||||||
if (BITApp.SynchronizationContext is not null)
|
|
||||||
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext,
|
|
||||||
BITApp.CancellationToken);
|
|
||||||
_isConnected.RemoveElement(this);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
private void OnError(ErrorCode errorCode, string message)
|
private void OnError(ErrorCode errorCode, string message)
|
||||||
{
|
{
|
||||||
|
@ -331,17 +325,31 @@ namespace BITKit.Net
|
||||||
|
|
||||||
public void ServerCommand<T>(T command = default)
|
public void ServerCommand<T>(T command = default)
|
||||||
{
|
{
|
||||||
Send(NetCommandType.Command,command);
|
using var ms = new MemoryStream();
|
||||||
|
using var writer = new BinaryWriter(ms);
|
||||||
|
writer.Write((byte)NetCommandType.Command);
|
||||||
|
BITBinary.Write(writer,command);
|
||||||
|
var bytes = ms.ToArray();
|
||||||
|
_commandQueue.Enqueue(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AllClientCommand<T>(T command = default)
|
public void AllClientCommand<T>(T command = default)
|
||||||
{
|
{
|
||||||
Send(NetCommandType.AllClientCommand,command);
|
using var ms = new MemoryStream();
|
||||||
|
using var writer = new BinaryWriter(ms);
|
||||||
|
writer.Write((byte)NetCommandType.AllClientCommand);
|
||||||
|
BITBinary.Write(writer,command);
|
||||||
|
var bytes = ms.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientCommand<T>(int id, T command)
|
public void ClientCommand<T>(int id, T command)
|
||||||
{
|
{
|
||||||
Send(NetCommandType.TargetCommand,id,command);
|
using var ms = new MemoryStream();
|
||||||
|
using var writer = new BinaryWriter(ms);
|
||||||
|
writer.Write((byte)NetCommandType.Command);
|
||||||
|
BITBinary.Write(writer,command);
|
||||||
|
var bytes = ms.ToArray();
|
||||||
|
_commandQueue.Enqueue(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async UniTask<T> GetFromServer<T>(string path = default,params object[] pars)
|
public async UniTask<T> GetFromServer<T>(string path = default,params object[] pars)
|
||||||
|
@ -363,8 +371,12 @@ namespace BITKit.Net
|
||||||
BITBinary.Write(writer,pars);
|
BITBinary.Write(writer,pars);
|
||||||
|
|
||||||
var bytes = ms.ToArray();
|
var bytes = ms.ToArray();
|
||||||
commandQueue.Enqueue(bytes);
|
_commandQueue.Enqueue(bytes);
|
||||||
var startTime = DateTime.Now;
|
var startTime = DateTime.Now;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if(DateTime.Now-startTime>TimeSpan.FromSeconds(5) || IsConnected is false)
|
if(DateTime.Now-startTime>TimeSpan.FromSeconds(5) || IsConnected is false)
|
||||||
|
@ -380,10 +392,6 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
if (typeof(T) == typeof(UniTaskVoid))
|
|
||||||
{
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
return value.As<T>();
|
return value.As<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,8 +411,16 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
|
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
|
||||||
if(att is null)continue;
|
if(att is null)continue;
|
||||||
_rpcMethods.TryAdd(methodInfo.Name, methodInfo);
|
_rpcMethods.AddOrUpdate(methodInfo.Name, methodInfo, (s, info) => methodInfo);
|
||||||
_rpcHandles.TryAdd(methodInfo.Name, rpcHandle);
|
_rpcHandles.AddOrUpdate(methodInfo.Name, rpcHandle, (s, o) => rpcHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var eventInfo in rpcHandle.GetType().GetEvents())
|
||||||
|
{
|
||||||
|
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>();
|
||||||
|
if(att is null)continue;
|
||||||
|
var handle = eventInfo.EventHandlerType.GetMethod("Invoke");
|
||||||
|
_rpcMethods.AddOrUpdate(handle.Name, handle, (s, info) => handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +452,13 @@ namespace BITKit.Net
|
||||||
|
|
||||||
public void SendRT(string rpcName, params object[] pars)
|
public void SendRT(string rpcName, params object[] pars)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
using var ms = new MemoryStream();
|
||||||
|
using var writer = new BinaryWriter(ms);
|
||||||
|
writer.Write((byte)NetCommandType.GetFromClient);
|
||||||
|
writer.Write(rpcName);
|
||||||
|
BITBinary.Write(writer,pars);
|
||||||
|
var bytes = ms.ToArray();
|
||||||
|
_commandQueue.Enqueue(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendTargetRT(int id, string rpcName, params object[] pars)
|
public void SendTargetRT(int id, string rpcName, params object[] pars)
|
||||||
|
@ -477,7 +499,7 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (commandQueue.TryDequeue(out var bytes))
|
while (_commandQueue.TryDequeue(out var bytes))
|
||||||
{
|
{
|
||||||
Traffic+=new float2(bytes.Length,0);
|
Traffic+=new float2(bytes.Length,0);
|
||||||
client.Send(bytes, KcpChannel.Reliable);
|
client.Send(bytes, KcpChannel.Reliable);
|
||||||
|
@ -506,17 +528,5 @@ namespace BITKit.Net
|
||||||
Traffic+=new float2(2,0);
|
Traffic+=new float2(2,0);
|
||||||
client.Send(new byte[]{0x01, 0x02}, KcpChannel.Reliable);
|
client.Send(new byte[]{0x01, 0x02}, KcpChannel.Reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Send(NetCommandType commandType,params object[] values)
|
|
||||||
{
|
|
||||||
var bytes = BinaryBuilder
|
|
||||||
.Create()
|
|
||||||
.Write((byte)commandType)
|
|
||||||
.WriteObject(values)
|
|
||||||
.Build();
|
|
||||||
commandQueue.Enqueue(bytes);
|
|
||||||
//client.Send(bytes, KcpChannel.Reliable);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,6 +37,8 @@ namespace BITKit.Net
|
||||||
private readonly ConcurrentDictionary<string,MethodInfo> _rpcMethods = new();
|
private readonly ConcurrentDictionary<string,MethodInfo> _rpcMethods = new();
|
||||||
private readonly ConcurrentDictionary<string,object> _rpcHandles = new();
|
private readonly ConcurrentDictionary<string,object> _rpcHandles = new();
|
||||||
|
|
||||||
|
private readonly ConcurrentQueue<(int id,byte[] bytes)> _sendQueue = new();
|
||||||
|
|
||||||
public KCPNetServer()
|
public KCPNetServer()
|
||||||
{
|
{
|
||||||
server = new KcpServer(
|
server = new KcpServer(
|
||||||
|
@ -64,6 +66,19 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
while (_sendQueue.TryDequeue(out var value))
|
||||||
|
{
|
||||||
|
if (server.connections.ContainsKey(value.id))
|
||||||
|
{
|
||||||
|
server.Send(value.id,value.bytes,KcpChannel.Reliable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIT4Log.Log<KCPNetServer>($"链接{value.id}已丢失,丢弃了{value.bytes.Length}个字节");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (server.IsActive() is false || ManualTick) return;
|
if (server.IsActive() is false || ManualTick) return;
|
||||||
server.Tick();
|
server.Tick();
|
||||||
}
|
}
|
||||||
|
@ -113,7 +128,11 @@ namespace BITKit.Net
|
||||||
public bool IsRunningServer => server.IsActive();
|
public bool IsRunningServer => server.IsActive();
|
||||||
public void SendMessageToClient(int id, string message)
|
public void SendMessageToClient(int id, string message)
|
||||||
{
|
{
|
||||||
Send(id,NetCommandType.Message,message);
|
using var ms = new MemoryStream();
|
||||||
|
using var writer = new BinaryWriter(ms);
|
||||||
|
writer.Write((byte)NetCommandType.Message);
|
||||||
|
writer.Write(message);
|
||||||
|
_sendQueue.Enqueue((id,ms.ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendMessageToAll(string message)
|
public void SendMessageToAll(string message)
|
||||||
|
@ -180,146 +199,156 @@ namespace BITKit.Net
|
||||||
BIT4Log.LogException(e);
|
BIT4Log.LogException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnDataInternel(int Id, ArraySegment<byte> bytes, KcpChannel channel)
|
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);
|
||||||
|
|
||||||
//BIT4Log.Log<INetServer>(Id);
|
try
|
||||||
|
|
||||||
var type = (NetCommandType)ms.ReadByte();
|
|
||||||
|
|
||||||
//BIT4Log.Log<INetServer>(type);
|
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case NetCommandType.Message:
|
var type = (NetCommandType)ms.ReadByte();
|
||||||
BIT4Log.Log<KCPNetServer>($"已收到消息,{Id}:{reader.ReadString()}");
|
|
||||||
break;
|
|
||||||
case NetCommandType.Command:
|
|
||||||
var command = BITBinary.Read(reader);
|
|
||||||
if (command is object[] { Length: 1 } objs) command = objs[0];
|
|
||||||
//BIT4Log.Log<KCPNetServer>($"已收到指令:{command},值:\n{JsonConvert.SerializeObject(command, Formatting.Indented)}");
|
|
||||||
_events.Invoke(command.GetType().FullName, command);
|
|
||||||
|
|
||||||
(int Id,object Command) tuple = (Id,command);
|
switch (type)
|
||||||
_events.InvokeDirect(command.GetType().FullName,tuple);
|
|
||||||
break;
|
|
||||||
case NetCommandType.Heartbeat:
|
|
||||||
server.Send(Id,new byte[]{(byte)NetCommandType.Heartbeat}, KcpChannel.Reliable);
|
|
||||||
break;
|
|
||||||
case NetCommandType.AllClientCommand:
|
|
||||||
foreach (var id in server.connections.Keys.ToArray())
|
|
||||||
{
|
|
||||||
server.Send(id,bytes,channel);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NetCommandType.TargetCommand:
|
|
||||||
var targetId = reader.ReadInt32();
|
|
||||||
server.Send(targetId,bytes,channel);
|
|
||||||
break;
|
|
||||||
case NetCommandType.Ping:
|
|
||||||
server.Send(Id,new byte[]{(byte)NetCommandType.Ping},channel);
|
|
||||||
break;
|
|
||||||
case NetCommandType.GetFromServer:
|
|
||||||
{
|
{
|
||||||
var requestId = reader.ReadInt32();
|
case NetCommandType.Message:
|
||||||
|
BIT4Log.Log<KCPNetServer>($"已收到消息,{Id}:{reader.ReadString()}");
|
||||||
|
break;
|
||||||
|
case NetCommandType.Command:
|
||||||
|
var command = BITBinary.Read(reader);
|
||||||
|
if (command is object[] { Length: 1 } objs) command = objs[0];
|
||||||
|
//BIT4Log.Log<KCPNetServer>($"已收到指令:{command},值:\n{JsonConvert.SerializeObject(command, Formatting.Indented)}");
|
||||||
|
_events.Invoke(command.GetType().FullName, command);
|
||||||
|
|
||||||
|
(int Id, object Command) tuple = (Id, command);
|
||||||
using var returnMS = new MemoryStream();
|
_events.InvokeDirect(command.GetType().FullName, tuple);
|
||||||
await using var returnWriter = new BinaryWriter(returnMS);
|
break;
|
||||||
returnWriter.Write((byte)NetCommandType.ReturnToClient);
|
case NetCommandType.Heartbeat:
|
||||||
returnWriter.Write(requestId);
|
_sendQueue.Enqueue((Id,new byte[] { (byte)NetCommandType.Heartbeat }));
|
||||||
|
break;
|
||||||
try
|
case NetCommandType.AllClientCommand:
|
||||||
{
|
foreach (var id in server.connections.Keys.ToArray())
|
||||||
if (reader.ReadBoolean())
|
|
||||||
{
|
{
|
||||||
var path = reader.ReadString();
|
_sendQueue.Enqueue((id,bytes.ToArray()));
|
||||||
var pars = BITBinary.Read(reader).As<object[]>();
|
}
|
||||||
|
break;
|
||||||
|
case NetCommandType.TargetCommand:
|
||||||
|
var targetId = reader.ReadInt32();
|
||||||
|
_sendQueue.Enqueue((targetId,bytes.ToArray()));
|
||||||
|
break;
|
||||||
|
case NetCommandType.Ping:
|
||||||
|
_sendQueue.Enqueue((Id,new byte[] { (byte)NetCommandType.Ping }));
|
||||||
|
break;
|
||||||
|
case NetCommandType.GetFromServer:
|
||||||
|
{
|
||||||
|
var requestId = reader.ReadInt32();
|
||||||
|
|
||||||
|
using var returnMS = new MemoryStream();
|
||||||
|
await using var returnWriter = new BinaryWriter(returnMS);
|
||||||
|
returnWriter.Write((byte)NetCommandType.ReturnToClient);
|
||||||
|
returnWriter.Write(requestId);
|
||||||
|
|
||||||
if (_rpcMethods.TryGetValue(path, out var methodInfo))
|
try
|
||||||
|
{
|
||||||
|
if (reader.ReadBoolean())
|
||||||
{
|
{
|
||||||
var isAwaitable = methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
|
var path = reader.ReadString();
|
||||||
var handle = _rpcHandles[path];
|
var pars = BITBinary.Read(reader).As<object[]>();
|
||||||
object value = null;
|
|
||||||
if (methodInfo.GetParameters().Length is 0)
|
|
||||||
{
|
|
||||||
pars = new object[]{};
|
|
||||||
}
|
|
||||||
if (isAwaitable)
|
|
||||||
{
|
|
||||||
dynamic result = methodInfo.Invoke(handle, pars)!;
|
|
||||||
|
|
||||||
value = await result;
|
|
||||||
|
if (_rpcMethods.TryGetValue(path, out var methodInfo))
|
||||||
|
{
|
||||||
|
var isAwaitable = methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
|
||||||
|
var handle = _rpcHandles[path];
|
||||||
|
object value = null;
|
||||||
|
if (methodInfo.GetParameters().Length is 0)
|
||||||
|
{
|
||||||
|
pars = new object[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAwaitable)
|
||||||
|
{
|
||||||
|
dynamic result = methodInfo.Invoke(handle, pars)!;
|
||||||
|
|
||||||
|
value = await result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = methodInfo.Invoke(handle, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
returnWriter.Write(true);
|
||||||
|
BITBinary.Write(returnWriter, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = methodInfo.Invoke(handle, pars);
|
throw new Exception($"未找到对应的Rpc方法:{path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
returnWriter.Write(true);
|
|
||||||
BITBinary.Write(returnWriter, value);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception($"未找到对应的Rpc方法:{path}");
|
var commandObj = BITBinary.Read(reader)
|
||||||
|
.As<object[]>()[0];
|
||||||
|
var funcName = commandObj.GetType()!.FullName!;
|
||||||
|
if (_rpc.TryGetValue(funcName, out var func))
|
||||||
|
{
|
||||||
|
var value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
|
||||||
|
returnWriter.Write(true);
|
||||||
|
BITBinary.Write(returnWriter, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"未找到对应的Rpc方法:{funcName}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var _bytes = returnMS.ToArray();
|
||||||
|
_sendQueue.Enqueue((Id,_bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
returnWriter.Write(false);
|
||||||
|
returnWriter.Write(e.Message);
|
||||||
|
|
||||||
|
var _bytes = returnMS.ToArray();
|
||||||
|
_sendQueue.Enqueue((Id,_bytes));
|
||||||
|
BIT4Log.LogException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NetCommandType.ReturnToServer:
|
||||||
|
{
|
||||||
|
var id = reader.ReadInt32();
|
||||||
|
if (reader.ReadBoolean())
|
||||||
|
{
|
||||||
|
var value = BITBinary.Read(reader);
|
||||||
|
_p2p.TryAdd(id, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var commandObj = BITBinary.Read(reader)
|
var message = reader.ReadString();
|
||||||
.As<object[]>()[0];
|
_p2p.TryAdd(id, new Exception(message));
|
||||||
var funcName = commandObj.GetType()!.FullName!;
|
|
||||||
if (_rpc.TryGetValue(funcName, out var func))
|
|
||||||
{
|
|
||||||
var value = await func.As<Func<object, UniTask<object>>>().Invoke(commandObj);
|
|
||||||
returnWriter.Write(true);
|
|
||||||
BITBinary.Write(returnWriter, value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception($"未找到对应的Rpc方法:{funcName}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var _bytes = returnMS.ToArray();
|
|
||||||
server.Send(Id, _bytes, KcpChannel.Reliable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
break;
|
||||||
{
|
default:
|
||||||
returnWriter.Write(false);
|
BIT4Log.Log<KCPNetServer>($"未知消息类型:{type},字节:{(byte)type}");
|
||||||
returnWriter.Write(e.Message);
|
BIT4Log.Log<KCPNetServer>(
|
||||||
|
$"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
|
||||||
var _bytes = returnMS.ToArray();
|
break;
|
||||||
server.Send(Id, _bytes, KcpChannel.Reliable);
|
|
||||||
BIT4Log.LogException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case NetCommandType.ReturnToServer:
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
var id = reader.ReadInt32();
|
ms.Close();
|
||||||
if (reader.ReadBoolean())
|
reader.Close();
|
||||||
{
|
BIT4Log.LogException(e);
|
||||||
var value = BITBinary.Read(reader);
|
|
||||||
_p2p.TryAdd(id, value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var message = reader.ReadString();
|
|
||||||
_p2p.TryAdd(id, new Exception(message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BIT4Log.Log<KCPNetServer>($"未知消息类型:{type},字节:{(byte)type}");
|
|
||||||
BIT4Log.Log<KCPNetServer>($"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnError(int Id, ErrorCode errorCode, string message)
|
private void OnError(int Id, ErrorCode errorCode, string message)
|
||||||
{
|
{
|
||||||
BIT4Log.Log<KCPNetServer>($"异常:{errorCode},{message}");
|
BIT4Log.Log<KCPNetServer>($"异常:{errorCode},{message}");
|
||||||
|
@ -367,7 +396,8 @@ namespace BITKit.Net
|
||||||
BITBinary.Write(writer,pars);
|
BITBinary.Write(writer,pars);
|
||||||
|
|
||||||
var bytes = ms.ToArray();
|
var bytes = ms.ToArray();
|
||||||
server.Send(id,bytes,KcpChannel.Reliable);
|
//server.Send(id,bytes,KcpChannel.Reliable);
|
||||||
|
_sendQueue.Enqueue((id,bytes));
|
||||||
var startTime = DateTime.Now;
|
var startTime = DateTime.Now;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -490,10 +520,8 @@ namespace BITKit.Net
|
||||||
.Write((byte)commandType)
|
.Write((byte)commandType)
|
||||||
.WriteObject(values)
|
.WriteObject(values)
|
||||||
.Build();
|
.Build();
|
||||||
if (server.connections.ContainsKey(id))
|
//server.Send(id,bytes, KcpChannel.Reliable);
|
||||||
{
|
_sendQueue.Enqueue((id,bytes));
|
||||||
server.Send(id,bytes, KcpChannel.Reliable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* 该接口为基础的网络接口,包括了网络服务,服务端接口,客户端接口的基本定义 e.g.
|
* 该接口为基础的网络接口,包括了网络服务,服务端接口,客户端接口的基本定义 e.g.
|
||||||
* ⭐INetProvider 网络服务接口的基本定义
|
* ⭐INetProvider 网络通信接口的基本定义
|
||||||
* ⭐INetServer 服务端接口的基本定义
|
* ⭐INetServer 服务端接口的基本定义
|
||||||
* ⭐INetClient 客户端接口的基本定义
|
* ⭐INetClient 客户端接口的基本定义
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,7 @@ using UnityEngine;
|
||||||
|
|
||||||
namespace BITKit
|
namespace BITKit
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method|AttributeTargets.Event)]
|
||||||
public sealed class NetRpcAttribute : Attribute
|
public sealed class NetRpcAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -67,6 +67,8 @@ namespace BITKit
|
||||||
ReciveFile=11,
|
ReciveFile=11,
|
||||||
ReturnToServer=12,
|
ReturnToServer=12,
|
||||||
ReturnToClient=13,
|
ReturnToClient=13,
|
||||||
|
TargetRpc=14,
|
||||||
|
AllRpc=15,
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 网络提供服务,包括了基础网络服务,e.g
|
/// 网络提供服务,包括了基础网络服务,e.g
|
||||||
|
|
|
@ -208,6 +208,7 @@ namespace BITKit.Net.Kcp
|
||||||
|
|
||||||
private void OnTick(float obj)
|
private void OnTick(float obj)
|
||||||
{
|
{
|
||||||
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||||
if (client.IsConnected is false && autoReconnect)
|
if (client.IsConnected is false && autoReconnect)
|
||||||
{
|
{
|
||||||
if (_reconnectInterval.AllowUpdate)
|
if (_reconnectInterval.AllowUpdate)
|
||||||
|
|
Loading…
Reference in New Issue