using System; 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.Entity; using UnityEngine; namespace JNGame.Network { public class JNTCPServer : JNServerBase { private int _port = 0; 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(); 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(); } protected async Task StartBind() { try { 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(); } } protected virtual async UniTask GetPort() { await UniTask.NextFrame(); return 9001; } public override void OnClose() { base.OnClose(); CloseNetty(); Debug.Log($"[JNTCPServer] 关闭连接"); } private async Task CloseNetty() { channel?.CloseAsync(); bossGroup?.ShutdownGracefullyAsync(); workerGroup?.ShutdownGracefullyAsync(); channel = null; bossGroup = null; workerGroup = null; } public void AllSend(int hId,IMessage data = null) { server.GetClients().ForEach(id => Send(id,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)); } } }