parent
5942a624c2
commit
ec8b7037c0
@ -0,0 +1,6 @@
|
||||
namespace HybirdFrameworkDriver.Common;
|
||||
|
||||
public interface IToBytes
|
||||
{
|
||||
byte[] ToBytes();
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
using System.Collections.Concurrent;
|
||||
using DotNetty.Buffers;
|
||||
using DotNetty.Transport.Channels;
|
||||
using HybirdFrameworkDriver.ModbusTcpMaster;
|
||||
using log4net;
|
||||
|
||||
namespace HybirdFrameworkDriver.Session;
|
||||
|
||||
|
||||
public class ModbusSession
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusSession));
|
||||
|
||||
public ModbusTcpMaster.ModbusTcpMaster ModbusTcpMaster;
|
||||
private String IpAddr { get; }
|
||||
public String Key { get; set; }
|
||||
|
||||
public ConcurrentDictionary<String, Object> BusinessMap { get;set; }
|
||||
public ModbusSession(ModbusTcpMaster.ModbusTcpMaster modbusTcpMaster)
|
||||
{
|
||||
this.ModbusTcpMaster = modbusTcpMaster;
|
||||
this.IpAddr = modbusTcpMaster.Ip;
|
||||
this.Key = modbusTcpMaster.connectId;
|
||||
}
|
||||
|
||||
|
||||
public bool Write<T>(ModbusProperty<T> property)
|
||||
{
|
||||
return ModbusTcpMaster.WriteValue(property);
|
||||
}
|
||||
public byte[]? Read(int registerNo, int length)
|
||||
{
|
||||
return ModbusTcpMaster.BatchRead(registerNo,length);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
using System.Net;
|
||||
using Autofac;
|
||||
using DotNetty.Codecs;
|
||||
using DotNetty.Handlers.Timeout;
|
||||
using DotNetty.Transport.Channels;
|
||||
using HybirdFrameworkCore.Autofac;
|
||||
using HybirdFrameworkDriver.Session;
|
||||
using log4net;
|
||||
|
||||
namespace HybirdFrameworkDriver.TcpClient;
|
||||
|
||||
public class ClientListenerHandler<TH, TD, TE> : ChannelHandlerAdapter where TH : IChannelHandler
|
||||
where TD : ByteToMessageDecoder, new()
|
||||
where TE : ChannelHandlerAdapter, new()
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(ClientListenerHandler<TH, TD, TE>));
|
||||
|
||||
public override void ChannelRegistered(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelRegistered(context);
|
||||
Log.Info("register " + context.Channel);
|
||||
}
|
||||
|
||||
public override void ChannelUnregistered(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelUnregistered(context);
|
||||
Log.Info("unregister " + context.Channel);
|
||||
}
|
||||
|
||||
public override void ChannelActive(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelActive(context);
|
||||
SessionMgr.RegisterSession(context.Channel, new IoSession(context.Channel));
|
||||
Log.Info("active " + context.Channel);
|
||||
}
|
||||
|
||||
public override void ChannelInactive(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelInactive(context);
|
||||
var ioSession = SessionMgr.GetSession(context.Channel.Id.ToString());
|
||||
SessionMgr.UnregisterSession(context.Channel);
|
||||
Log.Info("inactive " + context.Channel);
|
||||
//处理重连
|
||||
|
||||
TcpClient<TH, TD, TE> tcpClient = AppInfo.Container.Resolve<TcpClient<TH, TD, TE>>();
|
||||
IPEndPoint channelRemoteAddress = (IPEndPoint)ioSession.Channel.RemoteAddress;
|
||||
tcpClient.InitBootstrap(channelRemoteAddress.Address.ToString(), channelRemoteAddress.Port);
|
||||
tcpClient.Connect();
|
||||
}
|
||||
|
||||
public override void UserEventTriggered(IChannelHandlerContext context, object evt)
|
||||
{
|
||||
if (evt is IdleStateEvent)
|
||||
{
|
||||
if (context.Channel.Open)
|
||||
{
|
||||
context.Channel.CloseAsync();
|
||||
context.Channel.CloseCompletion.Wait();
|
||||
Log.Info($"channel {context.Channel.Id} timeout close");
|
||||
}
|
||||
}
|
||||
|
||||
base.UserEventTriggered(context, evt);
|
||||
Log.Info("UserEventTriggered " + context.Channel);
|
||||
}
|
||||
|
||||
public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
|
||||
{
|
||||
base.ExceptionCaught(context, exception);
|
||||
context.Channel.CloseAsync();
|
||||
Log.Info("exception " + context.Channel);
|
||||
}
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using Autofac;
|
||||
using Autofac.Core;
|
||||
using DotNetty.Codecs;
|
||||
using DotNetty.Handlers.Timeout;
|
||||
using DotNetty.Transport.Bootstrapping;
|
||||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Channels.Sockets;
|
||||
using HybirdFrameworkCore.Autofac;
|
||||
using HybirdFrameworkCore.Autofac.Attribute;
|
||||
using log4net;
|
||||
|
||||
namespace HybirdFrameworkDriver.TcpClient;
|
||||
|
||||
public class TcpClient<TH, TD, TE> where TH : IChannelHandler where TD: ByteToMessageDecoder,new() where TE: ChannelHandlerAdapter, new()
|
||||
{
|
||||
private Bootstrap? _bootstrap;
|
||||
|
||||
public IChannel Channel { get; set; }
|
||||
|
||||
public bool Connected { get; set; } = false;
|
||||
|
||||
public string Host { get; set; }
|
||||
public int Port { get; set; }
|
||||
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(TcpClient<TH, TD, TE>));
|
||||
|
||||
public void InitBootstrap(string host, int port)
|
||||
{
|
||||
Host = host;
|
||||
Port = port;
|
||||
_bootstrap = new Bootstrap();
|
||||
_bootstrap
|
||||
.Group(new MultithreadEventLoopGroup())
|
||||
.Channel<TcpSocketChannel>()
|
||||
.Option(ChannelOption.TcpNodelay, true)
|
||||
.Handler(new ActionChannelInitializer<ISocketChannel>(channel =>
|
||||
{
|
||||
var clientListenerHandler = new ClientListenerHandler<TH, TD, TE>();
|
||||
|
||||
IChannelPipeline pipeline = channel.Pipeline;
|
||||
// 监听器
|
||||
pipeline.AddLast(clientListenerHandler);
|
||||
pipeline.AddLast("idleStateHandler", new IdleStateHandler(30, 0, 0)); // 触发读取超时
|
||||
|
||||
|
||||
// 可以添加编解码器等
|
||||
ResolveDecode(pipeline);
|
||||
ResolveEncode(pipeline);
|
||||
|
||||
ResolveHandler(pipeline);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
private void ResolveEncode(IChannelPipeline pipeline)
|
||||
{
|
||||
pipeline.AddLast(new TE());
|
||||
}
|
||||
|
||||
private void ResolveDecode(IChannelPipeline pipeline)
|
||||
{
|
||||
pipeline.AddLast(new TD());
|
||||
}
|
||||
|
||||
private void ResolveHandler(IChannelPipeline pipeline)
|
||||
{
|
||||
|
||||
List<Type> list = new List<Type>();
|
||||
|
||||
foreach (IComponentRegistration reg in AppInfo.Container.ComponentRegistry.Registrations)
|
||||
{
|
||||
foreach (Service service in reg.Services)
|
||||
{
|
||||
if (service is TypedService ts)
|
||||
{
|
||||
if (MatchHandlers(ts))
|
||||
{
|
||||
list.Add(ts.ServiceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<TH> handlers = new List<TH>();
|
||||
foreach (var type in list)
|
||||
{
|
||||
object resolve = AppInfo.Container.Resolve(type);
|
||||
handlers.Add((TH) resolve);
|
||||
}
|
||||
|
||||
handlers.Sort((handler, msgHandler) =>
|
||||
{
|
||||
OrderAttribute? orderAttribute1 = handler.GetType().GetCustomAttribute<OrderAttribute>();
|
||||
OrderAttribute? orderAttribute2 = msgHandler.GetType().GetCustomAttribute<OrderAttribute>();
|
||||
int h1Order = orderAttribute1?.Order ?? 0;
|
||||
int h2Order = orderAttribute2?.Order ?? 0;
|
||||
return h1Order.CompareTo(h2Order);
|
||||
});
|
||||
foreach (var msgHandler in handlers)
|
||||
{
|
||||
pipeline.AddLast((IChannelHandler)msgHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private bool MatchHandlers(TypedService ts)
|
||||
{
|
||||
Type[] interfaces = ts.ServiceType.GetInterfaces();
|
||||
if (interfaces.Length > 0)
|
||||
{
|
||||
foreach (Type type in interfaces)
|
||||
{
|
||||
if (type == typeof(TH))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
Connected = false;
|
||||
int num = 1;
|
||||
while (!Connected)
|
||||
{
|
||||
Task<IChannel> task = _bootstrap!.ConnectAsync(new IPEndPoint(IPAddress.Parse(Host), Port));
|
||||
|
||||
Channel = task.Result;
|
||||
Connected = Channel.Open;
|
||||
|
||||
if (Connected)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(5000);
|
||||
num++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
Binary file not shown.
Loading…
Reference in new issue