103 lines
3.5 KiB
C#
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();
|
|
}
|
|
}
|
|
} |