upm_guru_kcp/Runtime/csharp-kcp/dotNetty-kcp/KcpServer.cs

103 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Numerics;
using System.Threading;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using dotNetty_kcp.thread;
using fec.fec;
namespace dotNetty_kcp
{
public class KcpServer
{
private IExecutorPool _executorPool;
private Bootstrap _bootstrap;
private IEventLoopGroup _eventLoopGroup;
private readonly List<IChannel> _localAddress = new List<IChannel>();
private IChannelManager _channelManager;
private IScheduleThread _scheduleThread;
public void init(int workSize, KcpListener kcpListener, ChannelConfig channelConfig, params int[] ports)
{
_executorPool = new ExecutorPool();
for (int i = 0; i < workSize; i++)
{
_executorPool.CreateMessageExecutor();
}
init(_executorPool, kcpListener, channelConfig, ports);
}
public void init(IExecutorPool executorPool, KcpListener kcpListener, ChannelConfig channelConfig, params int[] ports) {
if(channelConfig.UseConvChannel){
int convIndex = 0;
if(channelConfig.Crc32Check){
convIndex+=Ukcp.HEADER_CRC;
}
if(channelConfig.FecDataShardCount!=0&&channelConfig.FecParityShardCount!=0){
convIndex+= Fec.fecHeaderSizePlus2;
}
_channelManager = new ServerConvChannelManager(convIndex);
}else{
_channelManager = new ServerEndPointChannelManager();
}
int cpuNum = Environment.ProcessorCount;
int bindTimes = cpuNum;
_eventLoopGroup = new MultithreadEventLoopGroup(cpuNum);
_scheduleThread = new HashedWheelScheduleThread();
_bootstrap = new Bootstrap();
//TODO epoll模型 服务器端怎么支持?得试试成功没有
_bootstrap.Option(ChannelOption.SoReuseport, true);
// _bootstrap.Option(ChannelOption.SoReuseaddr, true);
_bootstrap.Group(_eventLoopGroup);
_bootstrap.ChannelFactory(() => new SocketDatagramChannel(AddressFamily.InterNetwork));
_bootstrap.Handler(new ActionChannelInitializer<SocketDatagramChannel>(channel =>
{
var pipeline = channel.Pipeline;
pipeline.AddLast(new ServerChannelHandler(_channelManager,channelConfig,executorPool,kcpListener,_scheduleThread));
}));
foreach (var port in ports)
{
// for (int i = 0; i < bindTimes; i++) {
var task = _bootstrap.BindAsync(port);
var channel = task.Result;
_localAddress.Add(channel);
// }
}
//TODO 如何启动关闭进程的钩子??
}
/**
* 同步关闭服务器
*/
public void stop() {
foreach (var channel in _localAddress)
{
channel.CloseAsync().Wait();
}
foreach (var ukcp in _channelManager.getAll())
{
ukcp.close();
}
_eventLoopGroup?.ShutdownGracefullyAsync();
_executorPool?.stop(false);
_scheduleThread.stop();
}
}
}