You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
4.4 KiB

8 months ago
using System.Reflection;
using Autofac;
7 months ago
using Autofac.Core;
8 months ago
using DotNetty.Codecs;
using DotNetty.Common.Internal.Logging;
9 months ago
using DotNetty.Handlers.Logging;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
8 months ago
using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Autofac.Attribute;
9 months ago
using log4net;
using Microsoft.Extensions.Logging;
using LogLevel = DotNetty.Handlers.Logging.LogLevel;
9 months ago
7 months ago
namespace HybirdFrameworkDriver.TcpServer;
/// <summary>
/// netty server
/// </summary>
public class TcpServer<TH, TD, TE> : IDisposable where TH : IChannelHandler
where TD : ByteToMessageDecoder, new()
where TE : ChannelHandlerAdapter, new()
9 months ago
{
7 months ago
private static readonly ILog Log = LogManager.GetLogger(typeof(TcpServer<TH, TD, TE>));
private static MultithreadEventLoopGroup? bossGroup;
private static MultithreadEventLoopGroup? workerGroup;
private static ServerBootstrap? bootstrap;
private int _port = 9000;
public LogLevel? LogLevel { get; set; }
7 months ago
public Action? ChannelInActiveAction { get; set; }
7 months ago
public TcpServer()
{
7 months ago
if (LogLevel != null)
{
InternalLoggerFactory.DefaultFactory.AddProvider(new Log4NetProvider());
}
7 months ago
bossGroup = new MultithreadEventLoopGroup();
workerGroup = new MultithreadEventLoopGroup();
bootstrap = new ServerBootstrap();
bootstrap
.Group(bossGroup, workerGroup) // 设置主和工作线程组
.Channel<TcpServerSocketChannel>() // 设置通道模式为TcpSocket
.Option(ChannelOption.SoKeepalive, true) //保持连接
.Handler(new LoggingHandler())
.ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
{
7 months ago
var serverListenerHandler = new ServerListenerHandler<TH, TD, TE>
{
7 months ago
ChannelInActiveAction = ChannelInActiveAction
};
var pipeline = channel.Pipeline;
pipeline.AddLast(new LoggingHandler());
7 months ago
pipeline.AddLast(serverListenerHandler);
pipeline.AddLast(new IdleStateHandler(0, 0, 180)); //检测空闲连接
//业务handler 这里是实际处理业务的Handler
ResolveEncode(pipeline);
ResolveDecode(pipeline);
ResolveHandler(pipeline);
}));
}
9 months ago
/// <summary>
7 months ago
/// ??netty
9 months ago
/// </summary>
7 months ago
public void Dispose()
9 months ago
{
7 months ago
Log.Info(this + " Dispose");
bossGroup?.ShutdownGracefullyAsync();
}
9 months ago
7 months ago
private void ResolveEncode(IChannelPipeline pipeline)
{
pipeline.AddLast(new TE());
}
9 months ago
7 months ago
private void ResolveDecode(IChannelPipeline pipeline)
{
pipeline.AddLast(new TD());
}
9 months ago
7 months ago
private void ResolveHandler(IChannelPipeline pipeline)
{
var list = new List<Type>();
9 months ago
7 months ago
foreach (var reg in AppInfo.Container.ComponentRegistry.Registrations)
foreach (var service in reg.Services)
if (service is TypedService ts)
if (MatchHandlers(ts))
list.Add(ts.ServiceType);
8 months ago
7 months ago
var handlers = new List<TH>();
foreach (var type in list)
7 months ago
{
7 months ago
var resolve = AppInfo.Container.Resolve(type);
handlers.Add((TH)resolve);
7 months ago
}
9 months ago
7 months ago
handlers.Sort((handler, msgHandler) =>
9 months ago
{
7 months ago
var orderAttribute1 = handler.GetType().GetCustomAttribute<OrderAttribute>();
var orderAttribute2 = msgHandler.GetType().GetCustomAttribute<OrderAttribute>();
var h1Order = orderAttribute1?.Order ?? 0;
var h2Order = orderAttribute2?.Order ?? 0;
return h1Order.CompareTo(h2Order);
});
foreach (var msgHandler in handlers) pipeline.AddLast(msgHandler);
}
9 months ago
7 months ago
private bool MatchHandlers(TypedService ts)
{
var interfaces = ts.ServiceType.GetInterfaces();
if (interfaces.Length > 0)
foreach (var type in interfaces)
if (type == typeof(TH))
return true;
9 months ago
7 months ago
return false;
}
public void Start(int port)
{
_port = port;
Log.Info(" Start Listen");
Task<IChannel>? channel = bootstrap?.BindAsync(_port);
Log.Info($"netty success listen {_port}");
9 months ago
}
8 months ago
}