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

192 lines
6.5 KiB
C#
Raw Normal View History

2023-08-30 05:50:21 +00:00
using System;
using System.Net;
using System.Net.Sockets;
using base_kcp;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using dotNetty_kcp.thread;
using fec;
using fec.fec;
namespace dotNetty_kcp
{
/**
* kcp
* 使:
* 1,tcpconv
* 2,kcpconv
* 3,kcp
* 4,60
*/
public class KcpClient
{
private Bootstrap bootstrap;
private IExecutorPool _executorPool;
private IChannelManager _channelManager;
private IEventLoopGroup _eventLoopGroup;
private IScheduleThread _scheduleThread;
private static IChannel bindLocal(Bootstrap bootstrap,EndPoint localAddress = null)
{
if (localAddress == null)
{
localAddress = new IPEndPoint(IPAddress.Any, 0);
}
return bootstrap.BindAsync(localAddress).Result;
}
public System.Threading.Tasks.Task<IChannel> BindLocal()
{
var localAddress = new IPEndPoint(IPAddress.Any, 0);
return bootstrap.BindAsync(localAddress);
}
public void init(ChannelConfig channelConfig,ExecutorPool executorPool,IEventLoopGroup eventLoopGroup)
{
if(channelConfig.UseConvChannel)
{
var convIndex = 0;
if(channelConfig.Crc32Check)
{
convIndex+=Ukcp.HEADER_CRC;
}
if(channelConfig.FecDataShardCount!=0&&channelConfig.FecParityShardCount!=0)
{
convIndex+= Fec.fecHeaderSizePlus2;
}
_channelManager = new ClientConvChannelManager(convIndex);
}
else
{
_channelManager = new ClientEndPointChannelManager();
}
//初始化线程池 创建一个线程就够了
_executorPool = executorPool;
_executorPool.CreateMessageExecutor();
_eventLoopGroup = eventLoopGroup;
_scheduleThread = new EventLoopScheduleThread();
bootstrap = new Bootstrap();
bootstrap.Group(_eventLoopGroup);
bootstrap.ChannelFactory(() => new SocketDatagramChannel(AddressFamily.InterNetwork));
bootstrap.Handler(new ActionChannelInitializer<SocketDatagramChannel>(channel =>
{
var pipeline = channel.Pipeline;
pipeline.AddLast(new ClientChannelHandler(_channelManager,channelConfig));
}));
}
public void init(ChannelConfig channelConfig)
{
var executorPool = new ExecutorPool();
executorPool.CreateMessageExecutor();
init(channelConfig,executorPool,new MultithreadEventLoopGroup());
}
/**
*
* 使kcpip
* 4Gwifi使
* @param ukcp
*/
public void reconnect(Ukcp ukcp){
if (!(_channelManager is ServerConvChannelManager))
{
throw new Exception("reconnect can only be used in convChannel");
}
ukcp.IMessageExecutor.execute(new ReconnectTask(ukcp,bootstrap));
}
private class ReconnectTask : ITask
{
private readonly Ukcp _ukcp;
private readonly Bootstrap _bootstrap;
public ReconnectTask(Ukcp ukcp, Bootstrap bootstrap)
{
_ukcp = ukcp;
_bootstrap = bootstrap;
}
public void execute()
{
_ukcp.user().Channel.CloseAsync();
var iChannel = bindLocal(_bootstrap);
_ukcp.user().Channel = iChannel;
}
}
public Ukcp connect(IChannel localChannel,EndPoint remoteAddress, ChannelConfig channelConfig, KcpListener kcpListener)
{
KcpOutput kcpOutput = new KcpOutPutImp();
ReedSolomon reedSolomon = null;
if (channelConfig.FecDataShardCount != 0 && channelConfig.FecParityShardCount != 0)
{
reedSolomon = ReedSolomon.create(channelConfig.FecDataShardCount, channelConfig.FecParityShardCount);
}
var _messageExecutor = _executorPool.GetAutoMessageExecutor();
var ukcp = new Ukcp(kcpOutput, kcpListener, _messageExecutor, reedSolomon, channelConfig);
var user = new User(localChannel, remoteAddress, localChannel.LocalAddress);
ukcp.user(user);
_channelManager.New(localChannel.LocalAddress, ukcp,null);
_messageExecutor.execute(new ConnectTask(ukcp, kcpListener));
var scheduleTask = new ScheduleTask( _channelManager, ukcp,_scheduleThread);
_scheduleThread.schedule(scheduleTask,TimeSpan.FromMilliseconds(ukcp.getInterval()));
return ukcp;
}
/**
*
*/
public Ukcp connect(EndPoint localAddress,EndPoint remoteAddress, ChannelConfig channelConfig, KcpListener kcpListener)
{
var channel = bindLocal(bootstrap,localAddress);
return connect(channel, remoteAddress, channelConfig, kcpListener);
}
/**
*
*/
public Ukcp connect(EndPoint remoteAddress, ChannelConfig channelConfig, KcpListener kcpListener)
{
var channel = bindLocal(bootstrap);
return connect(channel, remoteAddress, channelConfig, kcpListener);
}
public void stop()
{
foreach (var ukcp in _channelManager.getAll())
{
ukcp.close();
}
_executorPool?.stop(false);
if (_eventLoopGroup != null&&!_eventLoopGroup.IsShuttingDown)
{
_eventLoopGroup?.ShutdownGracefullyAsync().Wait();
}
_scheduleThread.stop();
}
}
}