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

208 lines
7.1 KiB
C#
Raw Permalink 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;
2023-09-01 12:20:57 +00:00
private IScheduleThread _scheduleThread;
2023-08-30 05:50:21 +00:00
2023-09-01 12:20:57 +00:00
private static IChannel bindLocal(Bootstrap bootstrap, EndPoint localAddress = null)
2023-08-30 05:50:21 +00:00
{
if (localAddress == null)
{
localAddress = new IPEndPoint(IPAddress.Any, 0);
}
return bootstrap.BindAsync(localAddress).Result;
}
public System.Threading.Tasks.Task<IChannel> BindLocal()
{
2023-09-04 02:21:13 +00:00
var localAddress = new IPEndPoint(IPAddress.Any, 0);
//var local_ip = GetLocalIPAddress();
//var localAddress = new IPEndPoint(IPAddress.Parse(local_ip), 0);
2023-08-30 05:50:21 +00:00
return bootstrap.BindAsync(localAddress);
}
2023-09-01 12:20:57 +00:00
public static string GetLocalIPAddress()
2023-08-30 05:50:21 +00:00
{
2023-09-01 12:20:57 +00:00
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("No network adapters with an IPv4 address in the system!");
}
public void init(ChannelConfig channelConfig, ExecutorPool executorPool, IEventLoopGroup eventLoopGroup)
{
if (channelConfig.UseConvChannel)
2023-08-30 05:50:21 +00:00
{
var convIndex = 0;
2023-09-01 12:20:57 +00:00
if (channelConfig.Crc32Check)
2023-08-30 05:50:21 +00:00
{
2023-09-01 12:20:57 +00:00
convIndex += Ukcp.HEADER_CRC;
2023-08-30 05:50:21 +00:00
}
2023-09-01 12:20:57 +00:00
if (channelConfig.FecDataShardCount != 0 && channelConfig.FecParityShardCount != 0)
2023-08-30 05:50:21 +00:00
{
2023-09-01 12:20:57 +00:00
convIndex += Fec.fecHeaderSizePlus2;
2023-08-30 05:50:21 +00:00
}
_channelManager = new ClientConvChannelManager(convIndex);
}
else
{
_channelManager = new ClientEndPointChannelManager();
}
//初始化线程池 创建一个线程就够了
_executorPool = executorPool;
_executorPool.CreateMessageExecutor();
_eventLoopGroup = eventLoopGroup;
2023-09-01 12:20:57 +00:00
2023-08-30 05:50:21 +00:00
_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;
2023-09-01 12:20:57 +00:00
pipeline.AddLast(new ClientChannelHandler(_channelManager, channelConfig));
2023-08-30 05:50:21 +00:00
}));
}
public void init(ChannelConfig channelConfig)
{
var executorPool = new ExecutorPool();
executorPool.CreateMessageExecutor();
2023-09-01 12:20:57 +00:00
init(channelConfig, executorPool, new MultithreadEventLoopGroup());
2023-08-30 05:50:21 +00:00
}
2023-09-01 12:20:57 +00:00
2023-08-30 05:50:21 +00:00
/**
*
* 使kcpip
* 4Gwifi使
* @param ukcp
*/
2023-09-01 12:20:57 +00:00
public void reconnect(Ukcp ukcp)
{
2023-08-30 05:50:21 +00:00
if (!(_channelManager is ServerConvChannelManager))
{
throw new Exception("reconnect can only be used in convChannel");
}
2023-09-01 12:20:57 +00:00
ukcp.IMessageExecutor.execute(new ReconnectTask(ukcp, bootstrap));
2023-08-30 05:50:21 +00:00
}
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;
}
}
2023-09-01 12:20:57 +00:00
public Ukcp connect(IChannel localChannel, EndPoint remoteAddress, ChannelConfig channelConfig, KcpListener kcpListener)
2023-08-30 05:50:21 +00:00
{
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);
2023-09-01 12:20:57 +00:00
_channelManager.New(localChannel.LocalAddress, ukcp, null);
2023-08-30 05:50:21 +00:00
_messageExecutor.execute(new ConnectTask(ukcp, kcpListener));
2023-09-01 12:20:57 +00:00
var scheduleTask = new ScheduleTask(_channelManager, ukcp, _scheduleThread);
_scheduleThread.schedule(scheduleTask, TimeSpan.FromMilliseconds(ukcp.getInterval()));
2023-08-30 05:50:21 +00:00
return ukcp;
}
/**
*
*/
2023-09-01 12:20:57 +00:00
public Ukcp connect(EndPoint localAddress, EndPoint remoteAddress, ChannelConfig channelConfig, KcpListener kcpListener)
2023-08-30 05:50:21 +00:00
{
2023-09-01 12:20:57 +00:00
var channel = bindLocal(bootstrap, localAddress);
2023-08-30 05:50:21 +00:00
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);
2023-09-01 12:20:57 +00:00
if (_eventLoopGroup != null && !_eventLoopGroup.IsShuttingDown)
2023-08-30 05:50:21 +00:00
{
_eventLoopGroup?.ShutdownGracefullyAsync().Wait();
}
_scheduleThread.stop();
}
}
}