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();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |