105 lines
3.3 KiB
C#
Raw Normal View History

2024-08-17 14:27:18 +08:00
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<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();
}
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<int> 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));
}
}
}