141 lines
5.8 KiB
C#
Raw Normal View History

2024-11-26 13:45:28 +08:00
using Abp.Dependency;
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using Serilog;
using System.Diagnostics;
using System.Runtime;
namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
{
public class DotNettyTcpServer : ISingletonDependency
{
private readonly Dictionary<byte, IChannelHandlerContext> connections = new Dictionary<byte, IChannelHandlerContext>();
// 定义 MessageReceived 事件
public event Action< byte, byte[], byte> MessageReceived; // 装置地址,功能码,消息
public event Action<Dictionary<byte, int[]>> deviceBoardStatesAction;
public DotNettyTcpServer()
{
//_dotNettyServerHandler = dotNettyServerHandler;
}
MultithreadEventLoopGroup bossGroup ;
MultithreadEventLoopGroup workerGroup ;
int maxFrameLength = 65536; // 设置最大帧长度
int lengthFieldOffset = 1; // 长度字段的偏移量,从启动字符之后开始
int lengthFieldLength = 2; // 长度字段的字节长度
int lengthAdjustment = -3; // 长度调整,将读取的长度减去启动字符和长度字段的字节数
int initialBytesToStrip = 0; // 保留所有字节
public async Task RunServerAsync(byte addr)
{
bossGroup = new MultithreadEventLoopGroup(1);
workerGroup = new MultithreadEventLoopGroup();
try
{
GCSettings.LatencyMode = GCLatencyMode.LowLatency;
var bootstrap = new ServerBootstrap();
bootstrap.Group(bossGroup, workerGroup)
.Channel<TcpServerSocketChannel>()
.Option(ChannelOption.SoBacklog, 100)
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
channel.Pipeline.AddLast(new LengthFieldBasedFrameDecoder(
maxFrameLength,
lengthFieldOffset,
lengthFieldLength,
lengthAdjustment,
initialBytesToStrip
));
channel.Pipeline.AddLast(new DotNettyServerHandler(connections, MessageReceived, deviceBoardStatesAction,addr));
channel.Pipeline.AddLast("hexDumpHandler", new HexDumpHandler());
}));
IChannel boundChannel = await bootstrap.BindAsync(3000);
Log.Information("服务器启动并监听端口 3000...");
}
finally
{
}
}
public async Task StopSeverAsync()
{
try
{
await Task.WhenAll(
bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)),
workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)));
}
catch (Exception ex)
{
Log.Information("服务器关闭并监听端口 7110...", "获取信息");
}
}
public async void SendMessageByIp(byte address, byte controlWord, byte functionCode , byte message)
{
if (connections.TryGetValue(address, out IChannelHandlerContext context))
{
try
{
//var buffer = Unpooled.WrappedBuffer(System.Text.Encoding.UTF8.GetBytes(message));
//context.WriteAndFlushAsync(buffer);
// 构建数据帧
byte[] buffer = new byte[7];
// 填入启动字符
buffer[0] = 0x16;
// 填入长度假设数据部分为50字节2字节长度字段+1字节地址+1字节标志位
byte dataLength = 7;
buffer[1] = 0; // 长度低字节
buffer[2] = dataLength; // 长度高字节
// 填入地址、应用控制字、功能类型
buffer[3] = address; // 示例地址
buffer[4] = controlWord; // 示例应用控制字
buffer[5] = functionCode; // 示例功能类型
buffer[6] = message;
// 填入数据部分
IByteBuffer wrappedBuffer = Unpooled.WrappedBuffer(buffer);
// 发送数据
await context.WriteAndFlushAsync(wrappedBuffer);
//Debug.WriteLine($"发送消息到 装置:{address}: {message}");
string hexString = BitConverter.ToString(buffer);
//MonitoringEventBus.LogHandler($"地址:{address} 功能码:{functionCode} 数据:{hexString}", "103客户端发送消息");
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString() );
}
}
else
{
Debug.WriteLine($"未找到 装置 为 {address} 的连接");
}
}
// 断开指定 IP 地址的连接
public void DisconnectByIp(byte addr)
{
if (connections.TryGetValue(addr, out IChannelHandlerContext context))
{
context.CloseAsync(); // 关闭连接
connections.Remove(addr); // 从字典中移除该连接
Debug.WriteLine($"断开 地址 为 {addr} 的连接");
}
else
{
Debug.WriteLine($"未找到 地址 为 {addr} 的连接");
}
}
}
}