|
|
|
|
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.ChargerManage.Handler;
|
|
|
|
|
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());
|
|
|
|
|
pipeline.AddLast(new CMD206Handler());
|
|
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
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, IChannelId id)
|
|
|
|
|
{
|
|
|
|
|
//foreach (IChannel channel in _container.Values)
|
|
|
|
|
//{
|
|
|
|
|
// channel.WriteAndFlushAsync(bytes);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
if (_container.ContainsKey(id))
|
|
|
|
|
_container[id].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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|