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.

126 lines
4.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections.Concurrent;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading.Channels;
using DotNetty.Buffers;
using DotNetty.Handlers.Logging;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using HybirdFrameworkCore.Autofac.Attribute;
using HybirdFrameworkServices.System;
using log4net;
namespace HybirdFrameworkServices.Netty
{
/// <summary>
/// netty server
/// </summary>
[Scope("SingleInstance")]
public class Server : IDisposable
{
private readonly ILog Log = LogManager.GetLogger(typeof(Server));
static MultithreadEventLoopGroup? bossGroup;
static MultithreadEventLoopGroup? workerGroup;
static ServerBootstrap? bootstrap;
static ConcurrentDictionary<IChannelId, IChannel> _container = ServerListenerHandler.Container;
private int _port = 9000;
public void connect(int port)
{
_port = port;
IByteBuffer delimiter = Unpooled.CopiedBuffer(new byte[] { 0xAA, 0xF5 });
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 =>
{
var serverListenerHandler = new ServerListenerHandler();
IChannelPipeline pipeline = channel.Pipeline;
pipeline.AddLast(new LoggingHandler(""));
pipeline.AddLast(serverListenerHandler);
//pipeline.AddLast(new FixedLengthFrameDecoder(12)); //定长数据12byte
pipeline.AddLast(new IdleStateHandler(0, 0, 180));//检测空闲连接
//pipeline.AddLast(msgHandler);
//业务handler 这里是实际处理业务的Handler
pipeline.AddLast(new CustomFrameDecoder(new IByteBuffer[] { delimiter }, false, false));
pipeline.AddLast(new CustomFrameEncoder());
//// 添加客户端连接监控Handler
//pipeline.AddLast(new ClientConnectionMonitorHandler());
//pipeline.AddLast("idleStateHandler", new IdleStateHandler(30, 0, 0)); // 触发读取超时
//pipeline.AddLast(new ReconnectHandler(this));
//pipeline.AddLast(new ClientHandler(this));
}));
Begin(_port);
}
public void Begin(int port)
{
_port = port;
Log.Info(" Start Listen");
Task<IChannel>? channel = bootstrap?.BindAsync(_port);
Log.Info($"netty success listen {_port}");
}
public void Send(byte[] bytes)
{
foreach (IChannel channel in _container.Values)
{
channel.WriteAndFlushAsync(bytes);
}
}
public void Send(byte[] bytes,string id)
{
foreach (IChannel channel in _container.Values)
{
channel.WriteAndFlushAsync(bytes);
}
}
/// <summary>
/// ??netty
/// </summary>
public void Dispose()
{
Log.Info(this + " Dispose");
bossGroup?.ShutdownGracefullyAsync();
}
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect(string ip)
{
Log.Info(this + " Disconnect");
foreach (IChannel channel in _container.Values)
{
string input = channel.RemoteAddress.ToString();
// 正则表达式匹配IPv4地址和端口号
string pattern = @"\[(::ffff:)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]:(\d+)";
Match match = Regex.Match(input, pattern);
// 获取IP地址不包括IPv6前缀
string ipAddress = match.Groups[2].Value;
if (ip == ipAddress)
channel.DisconnectAsync();
}
}
}
}