BITKit/Src/Core/Kcp/KcpNetServer.cs

635 lines
23 KiB
C#
Raw Normal View History

2023-06-29 14:57:11 +08:00
using System;
2024-06-08 10:07:40 +08:00
using System.Collections.Concurrent;
2023-08-23 01:59:26 +08:00
using System.Collections.Generic;
using System.Timers;
2023-06-29 14:57:11 +08:00
using Cysharp.Threading.Tasks;
using kcp2k;
2023-08-23 01:59:26 +08:00
using Newtonsoft.Json;
using Timer = System.Timers.Timer;
using System.IO;
using System.Linq;
using System.Net;
2024-06-08 15:12:48 +08:00
using System.Net.Sockets;
2024-06-12 16:01:56 +08:00
using System.Reflection;
2024-06-08 15:12:48 +08:00
using System.Threading.Tasks;
2024-07-06 16:14:29 +08:00
using System.Windows.Markup;
2023-08-23 01:59:26 +08:00
using BITKit.Net.Examples;
2023-06-29 14:57:11 +08:00
namespace BITKit.Net
{
public class KCPNetServer:INetServer,INetProvider
{
2024-06-20 17:28:56 +08:00
public string Name { get; set; } = "Default";
2024-06-20 10:55:18 +08:00
public int TickRate { get; set; } = 16;
2024-03-31 23:31:00 +08:00
public bool ManualTick { get; set; }
2023-10-06 23:43:19 +08:00
public event Action<int> OnClientConnected;
2023-06-29 14:57:11 +08:00
public event Action<int> OnClientDisconnected;
public event Action OnStartServer;
public event Action OnStopServer;
private readonly KcpServer server;
2023-08-23 01:59:26 +08:00
private readonly GenericEvent _events = new();
private readonly Timer _timer = new(100)
{
AutoReset = true
};
2024-03-31 23:31:00 +08:00
2024-06-08 10:07:40 +08:00
private int _index = 1001;
private readonly ConcurrentDictionary<int, object> _p2p = new();
2024-06-08 15:12:48 +08:00
private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = new();
2024-06-12 16:01:56 +08:00
private readonly ConcurrentDictionary<string,MethodInfo> _rpcMethods = new();
private readonly ConcurrentDictionary<string,object> _rpcHandles = new();
2024-06-20 17:28:56 +08:00
private readonly ConcurrentDictionary<int,DateTime> _lastHeartbeat = new();
2024-06-20 10:04:18 +08:00
private readonly ConcurrentQueue<(int id,byte[] bytes)> _sendQueue = new();
2024-06-22 17:58:05 +08:00
private readonly ConcurrentDictionary<int,int> _dropCount = new();
2024-06-20 10:55:18 +08:00
private DateTime _now=DateTime.Now;
private TimeSpan _interval=TimeSpan.FromSeconds(0.32);
2024-06-08 10:07:40 +08:00
private readonly byte[] _heartBeat = new byte[] { (byte)NetCommandType.Heartbeat };
2024-06-20 17:28:56 +08:00
2023-06-29 14:57:11 +08:00
public KCPNetServer()
{
server = new KcpServer(
OnConnected,
OnData,
OnDisconnect,
OnError,
KCPNet.Config
);
2023-08-23 01:59:26 +08:00
_timer.Elapsed += Tick;
BIT4Log.Log<KCPNetServer>("已创建KCP服务器");
2024-06-08 10:07:40 +08:00
2024-06-08 15:12:48 +08:00
AddCommandListener<SimplePing>(F);
2024-06-12 16:49:42 +08:00
AddRpcHandle(this);
2024-06-08 15:12:48 +08:00
return;
UniTask<SimplePing> F(SimplePing p)
2024-06-08 10:07:40 +08:00
{
2024-06-08 15:12:48 +08:00
p.EndTime = DateTime.Now;
return UniTask.FromResult(p);
}
2023-06-29 14:57:11 +08:00
}
2023-08-23 01:59:26 +08:00
private void Tick(object sender, ElapsedEventArgs e)
{
2024-06-20 10:55:18 +08:00
_now = DateTime.UtcNow;
2024-06-12 17:57:35 +08:00
try
{
2024-06-20 17:28:56 +08:00
foreach (var id in Connections.Keys.ToArray())
{
server.Send(id,_heartBeat , KcpChannel.Unreliable);
if (!_lastHeartbeat.TryGetValue(id, out var time)) continue;
2024-07-27 14:55:18 +08:00
if (!((_now - time).TotalSeconds > 3)) continue;
2024-06-20 17:28:56 +08:00
server.Disconnect(id);
_lastHeartbeat.TryRemove(id);
BIT4Log.Log<KCPNetServer>($"{Name}:链接{id}超时,已断开");
}
if (server.IsActive() is false || ManualTick) return;
server.Tick();
//BIT4Log.Log<KCPNetServer>($"{Name}目前有{server.connections.Count}个链接");
2024-06-22 17:58:05 +08:00
_dropCount.Clear();
2024-06-20 10:04:18 +08:00
while (_sendQueue.TryDequeue(out var value))
{
2024-06-20 17:28:56 +08:00
2024-06-20 10:04:18 +08:00
if (server.connections.ContainsKey(value.id))
{
2024-06-20 17:28:56 +08:00
server.Send(value.id, value.bytes, KcpChannel.Reliable);
2024-06-20 10:04:18 +08:00
}
else
{
2024-06-22 17:58:05 +08:00
int UpdateValueFactory(int i, int i1) => i1 + value.bytes.Length;
_dropCount.AddOrUpdate(value.id,value.bytes.Length,UpdateValueFactory);
2024-06-20 10:04:18 +08:00
}
}
2024-06-22 17:58:05 +08:00
foreach (var (id,length) in _dropCount)
{
BIT4Log.Log<KCPNetServer>($"未找到链接:{id},已丢弃字节数量:{length}");
}
2024-06-12 17:57:35 +08:00
}
2024-06-14 16:16:13 +08:00
catch (SocketException)
{
//丢失链接,有用户断开连接,通常是正常现象
}
2024-06-12 17:57:35 +08:00
catch (Exception exception)
{
BIT4Log.LogException(exception);
}
2023-08-23 01:59:26 +08:00
}
2024-06-22 17:58:05 +08:00
2023-06-29 14:57:11 +08:00
public void StartServer(ushort port = 27014)
{
2024-03-31 23:31:00 +08:00
if (IsRunningServer is false)
{
2024-06-14 17:50:29 +08:00
if (TickRate > 0)
{
_timer.Interval = 1000f / TickRate;
2024-06-20 17:28:56 +08:00
_interval = TimeSpan.FromSeconds(1.0 / TickRate);
2024-06-14 17:50:29 +08:00
}
2024-03-31 23:31:00 +08:00
OnStartServer?.Invoke();
server.Start(port);
_timer.Start();
BIT4Log.Log<KCPNetServer>($"已启动KCP服务器:{port}");
}
else
{
BIT4Log.Warning<KCPNetServer>($"KCP服务器已经启动,忽略此次请求");
}
2023-06-29 14:57:11 +08:00
}
public void StopServer(bool dispose = false)
{
2024-03-31 23:31:00 +08:00
if (IsRunningServer)
{
server.Stop();
OnStopServer?.Invoke();
_timer.Stop();
BIT4Log.Log<KCPNetServer>($"已停止KCP服务器");
}
else
{
BIT4Log.Warning<KCPNetServer>($"KCP服务器未运行,忽略此次请求");
}
2023-06-29 14:57:11 +08:00
}
public bool IsRunningServer => server.IsActive();
2023-08-23 01:59:26 +08:00
public void SendMessageToClient(int id, string message)
{
2024-06-20 10:04:18 +08:00
using var ms = new MemoryStream();
using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.Message);
writer.Write(message);
_sendQueue.Enqueue((id,ms.ToArray()));
2023-08-23 01:59:26 +08:00
}
public void SendMessageToAll(string message)
{
foreach (var Id in server.connections.Keys)
{
2023-10-24 23:38:22 +08:00
SendMessageToClient(Id,message);
2023-08-23 01:59:26 +08:00
}
}
public IDictionary<int, EndPoint> Connections =>
new Dictionary<int, EndPoint>(
server.connections.Select(x => new KeyValuePair<int, EndPoint>(x.Key, x.Value.remoteEndPoint)
));
2023-10-06 23:43:19 +08:00
2024-06-08 15:12:48 +08:00
public void Tick()
{
try
{
2024-06-20 17:28:56 +08:00
Tick(null,null);
2024-06-08 15:12:48 +08:00
}
catch (SocketException)
{
BIT4Log.Log<INetServer>("有用户断开连接,如有异常请检查");
}
}
2023-08-23 01:59:26 +08:00
public void HandShake()
{
2024-06-20 17:28:56 +08:00
foreach (var id in server.connections.Keys)
2023-08-23 01:59:26 +08:00
{
2024-06-20 17:28:56 +08:00
server.Send(id, new byte[]{0x03, 0x04}, KcpChannel.Reliable);
2023-08-23 01:59:26 +08:00
}
}
2024-06-20 17:28:56 +08:00
private void OnConnectedInternel(int id)
2023-06-29 14:57:11 +08:00
{
2024-06-20 17:28:56 +08:00
OnClientConnected?.Invoke(id);
ClientCommand(id,new NetClientAllocateIdCommand
2023-08-23 01:59:26 +08:00
{
2024-06-20 17:28:56 +08:00
Id = id,
Ip = server.connections[id].remoteEndPoint.ToString()
2023-08-23 01:59:26 +08:00
});
2024-06-20 17:28:56 +08:00
BIT4Log.Log<KCPNetServer>($"{id}已连接到:{Name}");
SendMessageToClient(id, $"成功连接到服务器:{Name}");
}
private void OnConnected(int Id)
{
// OnClientConnected?.Invoke(Id);
// ClientCommand(Id,new NetClientAllocateIdCommand
// {
// Id = Id,
// Ip = server.connections[Id].remoteEndPoint.ToString()
// });
// BIT4Log.Log<KCPNetServer>($"{Id}已连接到:{Name}");
// SendMessageToClient(Id, $"成功连接到服务器:{Name}");
2023-06-29 14:57:11 +08:00
}
private void OnDisconnect(int Id)
{
OnClientDisconnected?.Invoke(Id);
BIT4Log.Log<KCPNetServer>($"{Id}已断开");
}
2024-06-12 16:01:56 +08:00
private void OnData(int Id, ArraySegment<byte> bytes, KcpChannel channel)
{
try
{
OnDataInternel(Id, bytes, channel);
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
}
2024-06-20 10:04:18 +08:00
2024-06-12 16:01:56 +08:00
private async void OnDataInternel(int Id, ArraySegment<byte> bytes, KcpChannel channel)
2023-06-29 14:57:11 +08:00
{
2023-08-23 01:59:26 +08:00
using var ms = new MemoryStream(bytes.ToArray());
using var reader = new BinaryReader(ms);
2024-06-20 10:04:18 +08:00
try
2023-08-23 01:59:26 +08:00
{
2024-06-20 10:04:18 +08:00
var type = (NetCommandType)ms.ReadByte();
switch (type)
2024-06-11 15:39:09 +08:00
{
2024-06-20 10:04:18 +08:00
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);
_events.InvokeDirect(command.GetType().FullName, tuple);
break;
case NetCommandType.Heartbeat:
2024-06-20 17:28:56 +08:00
if (Connections.ContainsKey(Id))
{
_lastHeartbeat.AddOrUpdate(Id,OnAdd,OnUpdate);
}
2024-06-20 10:04:18 +08:00
break;
2024-06-20 17:28:56 +08:00
DateTime OnAdd(int arg)
{
OnConnectedInternel(Id);
return _now;
}
DateTime OnUpdate(int arg1, DateTime arg2)
{
return _now;
}
2024-06-20 10:04:18 +08:00
case NetCommandType.AllClientCommand:
foreach (var id in server.connections.Keys.ToArray())
{
_sendQueue.Enqueue((id,bytes.ToArray()));
}
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();
2024-06-11 15:39:09 +08:00
2024-06-20 10:04:18 +08:00
using var returnMS = new MemoryStream();
await using var returnWriter = new BinaryWriter(returnMS);
returnWriter.Write((byte)NetCommandType.ReturnToClient);
returnWriter.Write(requestId);
2024-06-11 15:39:09 +08:00
2024-06-20 10:04:18 +08:00
if (reader.ReadBoolean())
2024-06-12 16:01:56 +08:00
{
2024-06-20 10:04:18 +08:00
var path = reader.ReadString();
var pars = BITBinary.Read(reader).As<object[]>();
2024-06-12 16:49:42 +08:00
2024-06-20 10:04:18 +08:00
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[] { };
}
2024-07-17 17:06:45 +08:00
try
2024-06-20 10:04:18 +08:00
{
2024-07-17 17:06:45 +08:00
if (isAwaitable)
2024-07-06 16:14:29 +08:00
{
2024-07-17 17:06:45 +08:00
dynamic result = methodInfo.Invoke(handle, pars)!;
if (methodInfo.ReturnType == typeof(void) || methodInfo.ReturnType == typeof(UniTask))
{
await result;
value = -1;
}
else
{
value = await result;
}
2024-07-06 16:14:29 +08:00
}
else
{
2024-07-17 17:06:45 +08:00
value = methodInfo.Invoke(handle, pars);
2024-07-06 16:14:29 +08:00
}
2024-06-20 10:04:18 +08:00
}
2024-07-17 17:06:45 +08:00
catch (Exception e)
2024-06-20 10:04:18 +08:00
{
2024-07-17 17:06:45 +08:00
if(e is TargetInvocationException tie)
e = tie.InnerException;
returnWriter.Write(false);
returnWriter.Write(e.Message);
2024-06-20 10:04:18 +08:00
2024-07-17 17:06:45 +08:00
var _bytes = returnMS.ToArray();
_sendQueue.Enqueue((Id,_bytes));
BIT4Log.LogException(e);
return;
}
2024-06-20 10:04:18 +08:00
returnWriter.Write(true);
2024-07-06 16:14:29 +08:00
if (value is not null)
{
2024-07-29 14:37:00 +08:00
try
{
BITBinary.Write(returnWriter, value);
}
catch (NullReferenceException e)
{
throw;
}
catch (Exception e)
{
throw;
}
2024-07-06 16:14:29 +08:00
}
2024-06-12 16:49:42 +08:00
}
else
{
2024-06-20 10:04:18 +08:00
throw new Exception($"未找到对应的Rpc方法:{path}");
2024-06-12 16:49:42 +08:00
}
2024-06-12 16:01:56 +08:00
}
else
{
2024-06-20 10:04:18 +08:00
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}");
}
2024-06-12 16:01:56 +08:00
}
2024-06-11 15:39:09 +08:00
{
2024-06-20 10:04:18 +08:00
var _bytes = returnMS.ToArray();
_sendQueue.Enqueue((Id,_bytes));
2024-06-11 15:39:09 +08:00
}
2024-07-17 17:06:45 +08:00
2024-06-08 10:07:40 +08:00
}
2024-06-20 10:04:18 +08:00
break;
case NetCommandType.ReturnToServer:
2024-06-11 15:39:09 +08:00
{
2024-06-20 10:04:18 +08:00
var id = reader.ReadInt32();
if (reader.ReadBoolean())
{
var value = BITBinary.Read(reader);
_p2p.TryAdd(id, value);
}
else
{
var message = reader.ReadString();
_p2p.TryAdd(id, new Exception(message));
}
2024-06-11 15:39:09 +08:00
}
2024-06-20 10:04:18 +08:00
break;
default:
BIT4Log.Log<KCPNetServer>($"未知消息类型:{type},字节:{(byte)type}");
BIT4Log.Log<KCPNetServer>(
$"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
break;
2024-06-08 15:12:48 +08:00
}
2024-06-20 10:04:18 +08:00
}
catch (Exception e)
{
ms.Close();
reader.Close();
BIT4Log.LogException(e);
2023-08-23 01:59:26 +08:00
}
2023-06-29 14:57:11 +08:00
}
2024-06-20 10:04:18 +08:00
2024-06-20 17:28:56 +08:00
2023-06-29 14:57:11 +08:00
private void OnError(int Id, ErrorCode errorCode, string message)
{
BIT4Log.Log<KCPNetServer>($"异常:{errorCode},{message}");
}
public void ServerCommand<T>(T command = default)
{
2023-08-23 01:59:26 +08:00
_events.Invoke<T>(command);
2023-06-29 14:57:11 +08:00
}
2023-08-23 01:59:26 +08:00
public void AllClientCommand<T>(T command = default)
2023-06-29 14:57:11 +08:00
{
2023-08-23 01:59:26 +08:00
foreach (var id in server.connections.Keys.ToArray())
{
ClientCommand(id, command);
}
2023-06-29 14:57:11 +08:00
}
public void ClientCommand<T>(int id, T command)
{
2024-06-20 17:28:56 +08:00
using var ms = new MemoryStream();
using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.Command);
BITBinary.Write(writer,command);
_sendQueue.Enqueue((id,ms.ToArray()));
2023-06-29 14:57:11 +08:00
}
2024-06-12 16:49:42 +08:00
public UniTask<T> GetFromServer<T>(string path=default,params object[] pars)
2023-06-29 14:57:11 +08:00
{
throw new NotImplementedException();
}
2024-06-12 16:49:42 +08:00
public async UniTask<T> GetFromClient<T>(int id,string path=default, params object[] pars)
2023-06-29 14:57:11 +08:00
{
2024-06-20 10:55:18 +08:00
await UniTask.SwitchToThreadPool();
2024-06-08 15:12:48 +08:00
var index = _index++;
2024-06-20 17:28:56 +08:00
var ms = new MemoryStream();
var writer = new BinaryWriter(ms);
2024-06-08 15:12:48 +08:00
writer.Write((byte)NetCommandType.GetFromClient);
writer.Write(index);
2024-06-12 16:01:56 +08:00
if (string.IsNullOrEmpty(path))
{
writer.Write(false);
}
else
{
writer.Write(true);
writer.Write(path);
}
2024-06-12 16:49:42 +08:00
BITBinary.Write(writer,pars);
2024-06-08 15:12:48 +08:00
var bytes = ms.ToArray();
2024-06-20 17:28:56 +08:00
await ms.DisposeAsync();
await writer.DisposeAsync();
2024-06-20 10:04:18 +08:00
_sendQueue.Enqueue((id,bytes));
2024-06-20 10:55:18 +08:00
var startTime = _now;
2024-06-08 15:12:48 +08:00
while (true)
{
2024-06-20 17:28:56 +08:00
var time = _now - startTime;
if(time.TotalSeconds>5)
throw new TimeoutException($"等待超时,Id:{id},时间{time.TotalSeconds}");
2024-06-08 15:12:48 +08:00
if (_p2p.TryRemove(index, out var value))
{
2024-06-20 17:28:56 +08:00
//await BITApp.SwitchToMainThread();
2024-06-11 15:39:09 +08:00
if (value is Exception e)
{
throw e;
}
2024-06-17 10:40:01 +08:00
if (UniTask.CompletedTask is T t)
{
return t;
}
if (typeof(T) == typeof(UniTaskVoid))
{
return default;
}
2024-06-08 15:12:48 +08:00
return (T)value;
}
2024-06-20 10:55:18 +08:00
await Task.Delay(_interval);
2024-06-08 15:12:48 +08:00
}
2023-06-29 14:57:11 +08:00
}
public void AddRpcHandle(object rpcHandle)
{
2024-06-12 16:49:42 +08:00
foreach (var methodInfo in rpcHandle.GetType().GetMethods())
{
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
if(att is null)continue;
_rpcMethods.TryAdd(methodInfo.Name, methodInfo);
_rpcHandles.TryAdd(methodInfo.Name, rpcHandle);
}
2024-06-24 17:30:44 +08:00
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(eventInfo.Name, handle, (s, info) => handle);
_rpcHandles.AddOrUpdate(eventInfo.Name, rpcHandle, (s, info) => rpcHandle);
}
2024-06-12 16:49:42 +08:00
}
[NetRpc]
public string MyRpcTest(string hello)
{
return "Hello World";
}
[NetRpc]
public async UniTask<string> MyRpcTestAsync(string hello)
{
await Task.Delay(1000);
return $"{hello} World";
2023-06-29 14:57:11 +08:00
}
public void AddCommandListener<T>(Action<T> handle)
{
2023-08-23 01:59:26 +08:00
_events.AddListener<T>(handle);
2023-06-29 14:57:11 +08:00
}
2024-06-08 10:07:40 +08:00
2024-06-08 15:12:48 +08:00
public void AddCommandListener<T>(Func<T,UniTask<T>> func)
2024-06-08 10:07:40 +08:00
{
_rpc.TryAdd(typeof(T).FullName, F);
return;
2024-06-08 15:12:48 +08:00
async UniTask<object> F(object o)
2024-06-08 10:07:40 +08:00
{
2024-06-08 15:12:48 +08:00
return await func.Invoke((T)o);
2024-06-08 10:07:40 +08:00
}
}
2024-06-08 15:12:48 +08:00
public void RemoveCommandListener<T>(Func<T,UniTask<T>> func)
2024-06-08 10:07:40 +08:00
{
_rpc.TryRemove(typeof(T).FullName, out _);
}
2023-10-06 23:43:19 +08:00
public void AddCommandListenerWithId<T>(Action<int, T> handle)
{
2023-10-24 23:38:22 +08:00
_events.AddListenerDirect(typeof(T).FullName, Callback);
return;
void Callback(object value)
2023-10-06 23:43:19 +08:00
{
2023-10-24 23:38:22 +08:00
if (value is ValueTuple<int, object> tuple && tuple.Item2 is T)
2023-10-06 23:43:19 +08:00
{
2023-10-24 23:38:22 +08:00
handle.Invoke(tuple.Item1, (T)tuple.Item2);
2023-10-06 23:43:19 +08:00
}
2023-10-24 23:38:22 +08:00
else
{
Console.WriteLine(value);
}
}
2023-10-06 23:43:19 +08:00
}
2023-06-29 14:57:11 +08:00
2024-06-08 15:12:48 +08:00
public void KickClient(int id)
{
server.Disconnect(id);
}
2023-06-29 14:57:11 +08:00
public void RemoveCommandListener<T>(Action<T> handle)
{
2023-08-23 01:59:26 +08:00
_events.RemoveListener<T>(handle);
2023-06-29 14:57:11 +08:00
}
2024-06-08 10:07:40 +08:00
public void RemoveCommandListener<T>(Func<string, T> func)
{
throw new NotImplementedException();
}
2023-06-29 14:57:11 +08:00
public void SendRT(string rpcName, params object[] pars)
{
2024-06-20 17:28:56 +08:00
throw new NotImplementedException("服务端不支持此方法");
2023-06-29 14:57:11 +08:00
}
public void SendTargetRT(int id, string rpcName, params object[] pars)
{
2024-06-20 17:28:56 +08:00
using var ms = new MemoryStream();
using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.TargetRpc);
writer.Write(rpcName);
BITBinary.Write(writer,pars);
var bytes = ms.ToArray();
_sendQueue.Enqueue((id,bytes));
2023-06-29 14:57:11 +08:00
}
public void SendAllRT(string rpcName, params object[] pars)
{
2024-06-20 17:28:56 +08:00
using var ms = new MemoryStream();
using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.AllRpc);
writer.Write(rpcName);
BITBinary.Write(writer,pars);
var bytes = ms.ToArray();
foreach (var id in server.connections.Keys)
{
2024-06-20 10:04:18 +08:00
_sendQueue.Enqueue((id,bytes));
2024-06-20 17:28:56 +08:00
}
2023-08-23 01:59:26 +08:00
}
2023-06-29 14:57:11 +08:00
}
}