Tile服务器雏形..

This commit is contained in:
PC-20230316NUNE\Administrator
2024-08-19 11:51:17 +08:00
parent 894100ae37
commit a1f2730025
463 changed files with 37502 additions and 27925 deletions

View File

@@ -1,4 +1,5 @@
using Google.Protobuf;
using System;
using Google.Protobuf;
namespace Plugins.JNGame.Network.Entity
{
@@ -27,6 +28,7 @@ namespace Plugins.JNGame.Network.Entity
{
_hId = hId;
_id = id;
_bytes = Array.Empty<byte>();
}
//构造器

View File

@@ -59,8 +59,6 @@ namespace Plugins.JNGame.Network
}
public virtual void SendBytes(byte[] data){ }
public abstract Task StartConnect();
//获取字节大小
public int GetByteSize(int hId = 0)

View File

@@ -15,7 +15,7 @@ namespace Plugins.JNGame.Network
public class JNServerParam
{
public int Client;
public string Client;
public byte[] Message;

View File

@@ -26,7 +26,7 @@ namespace Plugins.JNGame.Network
await StartConnect();
}
public override async Task StartConnect()
public async Task StartConnect()
{
var url = $"{await this.GetUrl()}";

View File

@@ -2,96 +2,122 @@
using System.Net;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using Google.Protobuf;
using Plugins.JNGame.Network;
using Plugins.JNGame.Network.Action;
using Plugins.JNGame.Network.Entity;
using TestNetty.Client.Initializers;
using Plugins.JNGame.Network.Util;
using TouchSocket.Core;
using TouchSocket.Sockets;
using UnityEngine;
using NotImplementedException = System.NotImplementedException;
namespace Plugins.JNGame.Network
namespace JNGame.Network
{
public class JNTCPClient : JNClientBase
{
private IChannel clientChannel;
private IEventLoopGroup group;
private Bootstrap bootstrap;
public bool IsOpen => clientChannel is not null && clientChannel.Open;
private TcpClient tcpClient;
public bool IsOpen => tcpClient is not null && tcpClient.Online;
public override async Task OnInit()
{
tcpClient = new TcpClient();
await tcpClient.SetupAsync(
new TouchSocketConfig()
.ConfigurePlugins(a =>
{
a.UseReconnection(-1, true, 1000); //如需永远尝试连接tryCount设置为-1即可。
})
.SetTcpDataHandlingAdapter(() => new FixedHeaderPackageAdapter())
);
tcpClient.Connecting = OnConnecting;
tcpClient.Connected = OnConnected;//成功连接到服务器
tcpClient.Disconnected = OnDisconnected;//从服务器断开连接,当连接不成功时不会触发。
tcpClient.Received = OnReceived;
await base.OnInit();
await StartConnect();
tcpClient.Connect(await GetEndPoint());
}
public override async Task StartConnect()
/// <summary>
///
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
private Task OnConnecting(ITcpClient client, ConnectingEventArgs e)
{
if (!isStart) return;
await CloseNetty();
group = new MultithreadEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap
.Group(group)
.Channel<TcpSocketChannel>()
.Option(ChannelOption.TcpNodelay, true)
.Handler(new TcpClientInitializer(this));
try
{
if (bootstrap is not null)
{
Debug.Log($"[JNTCPClient] 开始连接");
clientChannel = await bootstrap.ConnectAsync( await GetEndPoint() );
Debug.Log($"[JNTCPClient] 连接成功");
}
}
catch (Exception e)
{
Debug.LogWarning(e.Message);
Debug.Log($"[JNTCPClient] 连接失败 1s后重试");
await UniTask.DelayFrame(1000);
await StartConnect();
}
Debug.Log($"[JNTCPClient] 开始连接服务器");
return Task.CompletedTask;
}
protected virtual async UniTask<IPEndPoint> GetEndPoint()
/// <summary>
/// 成功连接到服务器
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
private Task OnConnected(ITcpClient client, ConnectedEventArgs e)
{
await UniTask.NextFrame();
return new IPEndPoint(IPAddress.Parse("127.0.0.1"),9001);
Debug.Log($"[JNTCPClient] 服务器连接成功");
Dispatch(new JNetParam(_id++,(int)NActionEnum.ClientConnect));
return Task.CompletedTask;
}
/// <summary>
/// 从服务器断开连接,当连接不成功时不会触发。
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
private Task OnDisconnected(ITcpClientBase client, DisconnectEventArgs e)
{
Debug.Log($"[JNTCPClient] 服务器断开");
Dispatch(new JNetParam(_id++,(int)NActionEnum.ClientDisconnect));
return Task.CompletedTask;
}
/// <summary>
/// 接收到消息
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
private Task OnReceived(TcpClient client, ReceivedDataEventArgs e)
{
byte[] data = new byte[e.ByteBlock.Len];
Array.Copy(e.ByteBlock.Buffer,data, data.Length);
var param = NDataUtil.Parse(data);
Dispatch(param);
return Task.CompletedTask;
}
public override void SendBytes(byte[] data)
{
if (IsOpen)
{
tcpClient.Send(data);
}
}
public override void OnClose()
{
base.OnClose();
CloseNetty();
tcpClient.Close();
}
private async Task CloseNetty()
protected virtual async UniTask<string> GetEndPoint()
{
clientChannel?.CloseAsync();
if (group is not null) await group.ShutdownGracefullyAsync();
group = null;
clientChannel = null;
bootstrap = null;
}
public override void Send(int hId, IMessage data = null)
{
base.Send(hId, data);
if (IsOpen)
{
// clientChannel?.WriteAndFlushAsync(JNetParam.Build(this._id++, hId).SetData(data));
}
await UniTask.NextFrame();
return "127.0.0.1:9001";
}
}
}

View File

@@ -1,70 +1,118 @@
using System;

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using DotNetty.Buffers;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using DotRecast.Core.Collections;
using Google.Protobuf;
using JNGame.Network.Netty.TCP;
using Plugins.JNGame.Network;
using Plugins.JNGame.Network.Action;
using Plugins.JNGame.Network.Entity;
using Plugins.JNGame.Network.Util;
using TouchSocket.Core;
using TouchSocket.Sockets;
using UnityEngine;
namespace JNGame.Network
{
public class JNTCPServer : JNServerBase
{
private TcpService service;
private int _port = 0;
private int _port;
public int Port => _port;
private ServerBootstrap bootstrap;
private IEventLoopGroup bossGroup;
private IEventLoopGroup workerGroup;
private IChannel channel;
private TcpServerInitializer server;
public override async Task OnInit()
{
bossGroup = new MultithreadEventLoopGroup(1);
workerGroup = new MultithreadEventLoopGroup(4);
bootstrap = new ServerBootstrap();
bootstrap.Group(bossGroup, workerGroup);
bootstrap.Channel<TcpServerSocketChannel>();
bootstrap
.Option(ChannelOption.SoBacklog, 1024)
//ByteBuf的分配器(重用缓冲区)大小
.Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default)
.Option(ChannelOption.RcvbufAllocator, new FixedRecvByteBufAllocator(1024 * 8))
.ChildOption(ChannelOption.SoKeepalive, true) //保持长连接
.ChildOption(ChannelOption.TcpNodelay, true) //端口复用
.ChildOption(ChannelOption.SoReuseport, true)
//自定义初始化Tcp服务
.ChildHandler(server = new TcpServerInitializer(this));
await StartBind();
service = new TcpService();
await service.SetupAsync(
new TouchSocketConfig()
.SetTcpDataHandlingAdapter(() => new FixedHeaderPackageAdapter())
);
service.Connecting = OnConnecting;//有客户端正在连接
service.Connected = OnConnected;//有客户端连接
service.Disconnected = OnDisconnected;//有客户端断开连接
service.Received = OnReceived;//客户端接收到消息
await service.StartAsync(_port = await GetPort());//启动
}
protected async Task StartBind()
/// <summary>
/// 有客户端正在连接
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
private Task OnConnecting(SocketClient client, ConnectingEventArgs e)
{
try
Debug.Log($"[JNTCPServer] 有客户端正在连接");
return Task.CompletedTask;
}
/// <summary>
/// 有客户端连接
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
private Task OnConnected(SocketClient client, ConnectedEventArgs e)
{
Debug.Log($"[JNTCPServer] 有客户端连接成功");
Dispatch((int)NActionEnum.ClientConnect,new JNServerParam()
{
channel = await bootstrap.BindAsync(_port = await GetPort());
Debug.Log($"[JNTCPServer] 服务器创建成功");
}
catch (Exception e)
{
Debug.LogWarning(e.Message);
Debug.Log($"[JNTCPServer] 服务器创建失败 1s后重试");
await UniTask.DelayFrame(1000);
await StartBind();
}
Client = client.Id
});
return Task.CompletedTask;
}
/// <summary>
/// 有客户端断开连接
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
private Task OnDisconnected(SocketClient client, DisconnectEventArgs e)
{
Debug.Log($"[JNTCPServer] 有客户端断开连接");
Dispatch((int)NActionEnum.ClientDisconnect,new JNServerParam()
{
Client = client.Id
});
return Task.CompletedTask;
}
/// <summary>
/// 客户端接收到消息
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
private async Task OnReceived(SocketClient client, ReceivedDataEventArgs e)
{
byte[] data = new byte[e.ByteBlock.Len];
Array.Copy(e.ByteBlock.Buffer,data, data.Length);
var param = NDataUtil.Parse(data);
Dispatch(param.HId,new JNServerParam()
{
Client = client.Id,
Message = param.Bytes,
});
await UniTask.NextFrame();
}
public override void OnClose()
{
base.OnClose();
service.Stop();
}
protected virtual async UniTask<int> GetPort()
@@ -72,34 +120,22 @@ namespace JNGame.Network
await UniTask.NextFrame();
return 9001;
}
public override void OnClose()
public void Send(SocketClient client,int hId,IMessage data = null)
{
base.OnClose();
CloseNetty();
Debug.Log($"[JNTCPServer] 关闭连接");
}
private async Task CloseNetty()
{
channel?.CloseAsync();
bossGroup?.ShutdownGracefullyAsync();
workerGroup?.ShutdownGracefullyAsync();
channel = null;
bossGroup = null;
workerGroup = null;
var bytes = NDataUtil.Encrypt(JNetParam.Build(this._id++, hId).SetData(data));
_byteSize[hId] = bytes.Length;
service.SendAsync(client.Id, bytes);
}
public void AllSend(int hId,IMessage data = null)
{
server.GetClients().ForEach(id => Send(id,hId,data));
service.GetClients().ForEach(client =>
{
Send(client,hId,data);
});
}
public void Send(int client,int hId,IMessage data = null)
{
IChannelHandlerContext context = server.GetClient(client);
context.WriteAsync(JNetParam.Build(this._id++, hId).SetData(data));
}
}
}

View File

@@ -1,107 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using JNGame.Util;
using Plugins.JNGame.Network.Util;
using UnityEngine;
using NotImplementedException = System.NotImplementedException;
namespace Plugins.JNGame.Network
{
public abstract class JNTCPClient1 : JNClientBase
{
/// <summary>
/// 客户端
/// </summary>
/// <returns></returns>
private Socket client;
/// <summary>
/// 客户端线程
/// </summary>
/// <returns></returns>
private Thread thread;
/// <summary>
/// 是否连接
/// </summary>
public bool isConnect { get; private set; }
private Queue<byte[]> cache = new ();
public override async Task OnInit()
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(await GetEndPoint());
thread = new Thread(CreatConnectSocket);
thread.Start();
}
public override void OnClose()
{
Debug.Log($"[JNTCPClient] 关闭客户端");
base.OnClose();
client?.Close();
thread?.Abort();
}
protected virtual async UniTask<IPEndPoint> GetEndPoint()
{
await UniTask.NextFrame();
return new IPEndPoint(IPAddress.Parse("127.0.0.1"),9001);
}
private void CreatConnectSocket()
{
Debug.Log($"[JNTCPClient] 连接服务器成功");
isConnect = true;
PushCache();
byte[] bytes = new byte[102400];
try
{
while (true)
{
var max = client.Receive(bytes);
var message = new byte[max];
Array.Copy(bytes, message, max);
var param = NDataUtil.Parse(message);
Dispatch(param);
}
}
catch (Exception e)
{
// ignored
Debug.LogWarning(e.Message);
Debug.Log($"[JNTCPClient] 断开连接");
isConnect = false;
client.Close();
}
}
public override void SendBytes(byte[] data)
{
if (data is null || data.Length <= 0) return;
cache.Enqueue(data);
if (isConnect)
{
PushCache();
}
}
/// <summary>
/// 发送缓存
/// </summary>
public void PushCache()
{
while (isConnect && cache.TryDequeue(out var bytes))
{
NetTool.SendAsync(client,bytes);
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 9cd63835ebd243888fb11eb3fb168a92
timeCreated: 1723799588

View File

@@ -1,172 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using DotRecast.Core.Collections;
using Google.Protobuf;
using JNGame.Util.Types;
using Plugins.JNGame.Network.Action;
using Plugins.JNGame.Network.Entity;
using Plugins.JNGame.Network.Util;
using Plugins.JNGame.System;
using UnityEngine;
namespace Plugins.JNGame.Network
{
public abstract class JNTCPServer1 : JNServerBase
{
// /// <summary>
// /// 服务器
// /// </summary>
// /// <returns></returns>
// private TcpListener server;
//
// /// <summary>
// /// 服务器线程
// /// </summary>
// /// <returns></returns>
// private Thread thread;
// /// <summary>
// /// 客户端线程
// /// </summary>
// /// <returns></returns>
// private Dictionary<string,Socket> threads = new();
//
// private int _clientIndex = 0;
//
// /// <summary>
// /// 连接的客户端
// /// </summary>
// KeyValue<int,Socket> clients = new ();
//
// private int _port = 0;
// public int Port => _port;
//
//
// public override async Task OnInit()
// {
// await CreateServer();
// }
//
// /// <summary>
// /// 关闭服务器
// /// </summary>
// public override void OnClose()
// {
// Debug.Log($"[JNUDPServer] 关闭服务器");
// base.OnClose();
// server?.Stop();
// thread?.Abort();
// threads.ForEach(child => child.Value.Close());
// }
//
// /// <summary>
// /// 创建服务器
// /// </summary>
// private async UniTask CreateServer()
// {
//
// server = new TcpListener(IPAddress.Any,_port = await GetPort());
// server.Start();
// thread = new Thread(CreatConnectSocket);
// thread.Start();
//
// }
//
// protected virtual async UniTask<int> GetPort()
// {
// await UniTask.NextFrame();
// return 9001;
// }
//
//
// /// <summary>
// /// 接受监听后保存生成的通信客户端,并开启线程监听通信客户端消息
// /// </summary>
// void CreatConnectSocket()
// {
// Debug.Log($"[JNTCPServer] 创建服务器成功");
// while (true)
// {
// _clientIndex += 1;
// Socket socket = server.AcceptSocket();
// clients.Add(_clientIndex,socket);
// Thread thread1 = new Thread(() => { ListenConnectSocket(socket); });
// thread1.Start();
// }
// }
//
// /// <summary>
// /// 接受通信客户端消息并对消息进行处理
// /// </summary>
// /// <param name="socket"></param>
// void ListenConnectSocket(Socket socket)
// {
// Debug.Log($"[JNTCPServer] 客户端连接");
// //客户端连接
// _event.Dispatch($"{(int)NActionEnum.ClientConnect}",new JNServerParam()
// {
// Client = socket,
// Message = Array.Empty<byte>()
// });
// byte[] bytes = new byte[102400];
// try
// {
// while (true)
// {
// var max = socket.Receive(bytes);
// var message = new byte[max];
// if (max >= 102400)
// {
// throw new Exception($"[JNTCPServer] 超出最大接收{max}");
// }
// Array.Copy(bytes,message,max);
// var param = NDataUtil.Parse(message);
// _byteSize[param.HId] = param.Bytes.Length;
// _event.Dispatch($"{param.HId}",new JNServerParam()
// {
// Client = socket,
// Message = param.Bytes
// });
// }
// }
// catch (Exception e)
// {
// Debug.LogWarning(e.Message);
// Debug.Log($"[JNTCPServer] 断开客户端连接");
// //客户端断开
// _event.Dispatch($"{(int)NActionEnum.ClientDisconnect}",new JNServerParam()
// {
// Client = socket,
// Message = Array.Empty<byte>()
// });
// socket.Close();
// clients.RemoveByValue(socket);
// }
// }
//
// public void Send(Socket client,int hId,IMessage data = null)
// {
// var bytes = NDataUtil.Encrypt(JNetParam.Build(this._id++, hId).SetData(data));
// _byteSize[hId] = bytes.Length;
// client.SendAsync(bytes,SocketFlags.None);
// }
//
// public void AllSend(int hId,IMessage data = null)
// {
// clients.Values.ForEach(child =>
// {
// Send(child.Value, hId, data);
// });
// }
//
public override Task OnInit()
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: c0133b6e17024e67a3e0c86689c7ba9b
timeCreated: 1723725100

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 5da486bbb35a4830bbf04c02e4d64dae
timeCreated: 1723773802

View File

@@ -1,34 +0,0 @@
using System;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
namespace JNGame.Network.Netty
{
/// <summary>
/// Heartbeat Handler Class.
/// </summary>
public class HeartBeatHandler : ChannelHandlerAdapter
{
/// <summary>
/// Heart Beat Handler.
/// </summary>
/// <param name="context"></param>
/// <param name="evt"></param>
public override void UserEventTriggered(IChannelHandlerContext context, object evt)
{
var eventState = evt as IdleStateEvent;
if (eventState != null)
{
if (eventState.State == IdleState.ReaderIdle)
{
context.Channel.Flush();
context.Channel.CloseAsync();
}
}
else
{
base.UserEventTriggered(context, evt);
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 428846a1397f4426b81f1b79876325ef
timeCreated: 1723775429

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: b093de57a09748848035e479d1248ea4
timeCreated: 1723773808

View File

@@ -1,111 +0,0 @@
using System;
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using JNGame.Util.Types;
using Plugins.JNGame.Network;
using Plugins.JNGame.Network.Action;
using Plugins.JNGame.Network.Entity;
using UnityEngine;
namespace JNGame.Network.Netty.TCP
{
public class TcpClientHandler : ChannelHandlerAdapter
{
private JNClientBase root;
public TcpClientHandler(JNClientBase client)
{
root = client;
}
/// <summary>
/// 逻辑处理器被添加
/// </summary>
/// <param name="context"></param>
public override void HandlerAdded(IChannelHandlerContext context)
{
base.HandlerAdded(context);
}
/// <summary>
/// 绑定到线程
/// </summary>
/// <param name="context"></param>
public override void ChannelRegistered(IChannelHandlerContext context)
{
base.ChannelRegistered(context);
}
/// <summary>
/// 准备就绪
/// </summary>
/// <param name="context"></param>
public override void ChannelActive(IChannelHandlerContext context)
{
base.ChannelActive(context);
Debug.Log($"[TcpClientHandler] 连接成功: {context.Channel.RemoteAddress}");
}
/// <summary>
/// 有数据可读
/// </summary>
/// <param name="context"></param>
/// <param name="message"></param>
public override void ChannelRead(IChannelHandlerContext context, object message)
{
base.ChannelRead(context, message);
if (message is not JNetParam data) return;
root.Dispatch(data);
}
/// <summary>
/// 某次数据读完
/// </summary>
/// <param name="context"></param>
public override void ChannelReadComplete(IChannelHandlerContext context)
{
base.ChannelReadComplete(context);
}
/// <summary>
/// 被关闭
/// </summary>
/// <param name="context"></param>
public override void ChannelInactive(IChannelHandlerContext context)
{
base.ChannelInactive(context);
}
/// <summary>
/// 取消线程(NioEventLoop) 的绑定
/// </summary>
/// <param name="context"></param>
public override void ChannelUnregistered(IChannelHandlerContext context)
{
base.ChannelUnregistered(context);
context.Channel.EventLoop.Schedule(() =>
{
Debug.Log($"重连接: {context.Channel.RemoteAddress}");
root.StartConnect();
}, new TimeSpan(1000));
}
/// <summary>
/// 逻辑处理器被移除
/// </summary>
/// <param name="context"></param>
public override void HandlerRemoved(IChannelHandlerContext context)
{
base.HandlerRemoved(context);
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 8a6cf562019b4e4eaf5fae1b4bb2b19f
timeCreated: 1723799944

View File

@@ -1,34 +0,0 @@
using DotNetty.Handlers.Logging;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using JNGame.Network.Netty;
using JNGame.Network.Netty.TCP;
using Plugins.JNGame.Network;
using TestNetty.Service.Handlers;
namespace TestNetty.Client.Initializers
{
public class TcpClientInitializer : ChannelInitializer<ISocketChannel>
{
private JNClientBase root;
private TcpClientHandler handler;
public TcpClientInitializer(JNClientBase server)
{
root = server;
handler = new TcpClientHandler(root);
}
protected override void InitChannel(ISocketChannel channel)
{
IChannelPipeline pipeline = channel.Pipeline;
pipeline.AddLast(new IdleStateHandler(30, 30, 60 * 5));
pipeline.AddLast(new HeartBeatHandler());
pipeline.AddLast("encoder", new TcpEncoderHandler());
pipeline.AddLast("decoder", new TcpDecoderHandler());
pipeline.AddLast(handler);
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 96db8fb3f65d44b798bc06f95a8246bb
timeCreated: 1723799785

View File

@@ -1,36 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using System.Collections.Generic;
using Plugins.JNGame.Network.Util;
namespace TestNetty.Service.Handlers
{
/// <summary>
/// Decoder Packet
/// </summary>
public class TcpDecoderHandler : ByteToMessageDecoder
{
//准备读取的消息长度
private int? length;
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
if (length is null && input.ReadableBytes >= 4)
{
length = input.ReadInt();
}
if (length is not null && input.ReadableBytes >= length)
{
IByteBuffer result = input.ReadBytes(length.Value);
output.Add(NDataUtil.Parse(result.Array));
result.Clear();
length = null;
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 9487ff44b5354bc4843ac7320680c10f
timeCreated: 1723773916

View File

@@ -1,22 +0,0 @@
using System;
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using Plugins.JNGame.Network.Entity;
using Plugins.JNGame.Network.Util;
namespace TestNetty.Service.Handlers
{
/// <summary>
/// Encoder Packet
/// </summary>
public class TcpEncoderHandler : MessageToByteEncoder<JNetParam>
{
protected override void Encode(IChannelHandlerContext context, JNetParam message, IByteBuffer output)
{
var data = NDataUtil.Encrypt(message);
output.WriteInt(data.Length);//4-8
output.WriteBytes(data);
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 11f81d1e8543432c8226b6c42b605010
timeCreated: 1723773916

View File

@@ -1,11 +0,0 @@
using Plugins.JNGame.Network.Entity;
namespace JNGame.Network.Netty.TCP
{
public class TcpPacket
{
public int Checkbit;
public int Length;
public JNetParam Data;
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: b5008afe7a554eafb1c684bef86362b0
timeCreated: 1723774619

View File

@@ -1,154 +0,0 @@
using System;
using DotNetty.Transport.Channels;
using JNGame.Util.Types;
using Plugins.JNGame.Network;
using Plugins.JNGame.Network.Action;
using Plugins.JNGame.Network.Entity;
using UnityEngine;
namespace JNGame.Network.Netty.TCP
{
public class TcpServerHandler : ChannelHandlerAdapter
{
private int _index = 0;
public int Next()
{
return _index++;
}
private JNServerBase root;
public readonly KeyValue<IChannelHandlerContext, int> ClientInts = new();
public TcpServerHandler(JNServerBase server)
{
root = server;
}
/// <summary>
/// 逻辑处理器被添加
/// </summary>
/// <param name="context"></param>
public override void HandlerAdded(IChannelHandlerContext context)
{
base.HandlerAdded(context);
ClientInts.Add(context,Next());
}
/// <summary>
/// 绑定到线程
/// </summary>
/// <param name="context"></param>
public override void ChannelRegistered(IChannelHandlerContext context)
{
base.ChannelRegistered(context);
}
/// <summary>
/// 准备就绪
/// </summary>
/// <param name="context"></param>
public override void ChannelActive(IChannelHandlerContext context)
{
base.ChannelActive(context);
if (!(ClientInts.TryGetValueByKey(context,out var id)))
{
context.CloseAsync();
return;
}
Debug.Log($"[TcpServerHandler] 连接成功: {context.Channel.RemoteAddress}");
//客户端连接
root.Dispatch((int)NActionEnum.ClientConnect,new JNServerParam()
{
Client = id,
Message = Array.Empty<byte>()
});
}
/// <summary>
/// 有数据可读
/// </summary>
/// <param name="context"></param>
/// <param name="message"></param>
public override void ChannelRead(IChannelHandlerContext context, object message)
{
base.ChannelRead(context, message);
if (message is not JNetParam data) return;
if (!(ClientInts.TryGetValueByKey(context,out var id)))
{
context.CloseAsync();
return;
}
root.Dispatch(data.HId,new JNServerParam()
{
Client = id,
Message = data.Bytes
});
}
/// <summary>
/// 某次数据读完
/// </summary>
/// <param name="context"></param>
public override void ChannelReadComplete(IChannelHandlerContext context)
{
base.ChannelReadComplete(context);
}
/// <summary>
/// 被关闭
/// </summary>
/// <param name="context"></param>
public override void ChannelInactive(IChannelHandlerContext context)
{
base.ChannelInactive(context);
if (!(ClientInts.TryGetValueByKey(context,out var id)))
{
context.CloseAsync();
return;
}
Debug.Log($"[TcpServerHandler] 断开连接: {context.Channel.RemoteAddress}");
//客户端断开
root.Dispatch((int)NActionEnum.ClientDisconnect,new JNServerParam()
{
Client = id,
Message = Array.Empty<byte>()
});
}
/// <summary>
/// 取消线程(NioEventLoop) 的绑定
/// </summary>
/// <param name="context"></param>
public override void ChannelUnregistered(IChannelHandlerContext context)
{
base.ChannelUnregistered(context);
}
/// <summary>
/// 逻辑处理器被移除
/// </summary>
/// <param name="context"></param>
public override void HandlerRemoved(IChannelHandlerContext context)
{
base.HandlerRemoved(context);
ClientInts.RemoveByKey(context);
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 70f2f7800eb14ae189df47eb04e775aa
timeCreated: 1723776097

View File

@@ -1,42 +0,0 @@
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using Plugins.JNGame.Network;
using TestNetty.Service.Handlers;
namespace JNGame.Network.Netty.TCP
{
public class TcpServerInitializer : ChannelInitializer<ISocketChannel>
{
private JNServerBase root;
private TcpServerHandler handler;
public TcpServerInitializer(JNServerBase server)
{
root = server;
handler = new TcpServerHandler(root);
}
protected override void InitChannel(ISocketChannel channel)
{
IChannelPipeline pipeline = channel.Pipeline;
pipeline.AddLast(new IdleStateHandler(30,30,60 * 5));//心跳
pipeline.AddLast(new HeartBeatHandler());
pipeline.AddLast("encoder", new TcpEncoderHandler());
pipeline.AddLast("decoder", new TcpDecoderHandler());
pipeline.AddLast(handler);
}
public IChannelHandlerContext GetClient(int index)
{
return handler.ClientInts.Value2Key(index);
}
public int[] GetClients()
{
return handler.ClientInts.Values;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 5c734c16eb6b4ff98f41bb63524f3209
timeCreated: 1723773874