Преглед на файлове

1. 传输协议 netty 客户端服务端
2. 版本更新

Shun преди 2 години
родител
ревизия
39aa0a08ae

+ 2 - 2
src/YSAI.DAQ/YSAI.Can/YSAI.Can.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
 	  <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-	  <Version>1.0.0.25</Version>
+	  <Version>1.0.0.26</Version>
 	  <Authors>Shun</Authors>
 	  <Company>YSAI</Company>
 	  <Product>SCADA</Product>
@@ -17,7 +17,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.61" />
   </ItemGroup>
 
   <ItemGroup>

+ 7 - 0
src/YSAI.DAQ/YSAI.DAQ.sln

@@ -95,6 +95,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YSAI.Pack.Param", "YSAI.Pac
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YSAI.Netty", "YSAI.Netty\YSAI.Netty.csproj", "{D757285D-0B7C-47C4-BC54-744B6E2A7E61}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YSAI.Netty.Pack", "YSAI.Netty.Pack\YSAI.Netty.Pack.csproj", "{B2100081-54BC-4500-80D9-2A5B1CBCFD1B}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -249,6 +251,10 @@ Global
 		{D757285D-0B7C-47C4-BC54-744B6E2A7E61}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{D757285D-0B7C-47C4-BC54-744B6E2A7E61}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{D757285D-0B7C-47C4-BC54-744B6E2A7E61}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B2100081-54BC-4500-80D9-2A5B1CBCFD1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B2100081-54BC-4500-80D9-2A5B1CBCFD1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B2100081-54BC-4500-80D9-2A5B1CBCFD1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B2100081-54BC-4500-80D9-2A5B1CBCFD1B}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -295,6 +301,7 @@ Global
 		{1CFDF4C1-53F7-4A32-B83D-4B99AFC95A8D} = {12CB0510-7B1E-4518-AA3B-412A4D323D42}
 		{36696247-658B-445E-9C05-A815B73F248A} = {1EBA4FD7-DF52-49A0-8AA4-9E61ABC614F5}
 		{D757285D-0B7C-47C4-BC54-744B6E2A7E61} = {9D8EDBBA-7A97-4D84-9B12-7FCC2F834046}
+		{B2100081-54BC-4500-80D9-2A5B1CBCFD1B} = {1EBA4FD7-DF52-49A0-8AA4-9E61ABC614F5}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {5D5D3927-6714-40C0-84EA-44C5BA4C5E87}

+ 2 - 2
src/YSAI.DAQ/YSAI.DB/YSAI.DB.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
 	  <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-	  <Version>1.0.0.25</Version>
+	  <Version>1.0.0.26</Version>
 	  <Authors>Shun</Authors>
 	  <Company>YSAI</Company>
 	  <Product>SCADA</Product>
@@ -18,7 +18,7 @@
 		<PackageReference Include="System.Data.OracleClient" Version="1.0.8" />
 		<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
 		<PackageReference Include="System.Data.SQLite" Version="1.0.118" />
-		<PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+		<PackageReference Include="YSAI.Core" Version="1.0.0.61" />
 	</ItemGroup>
 	<!--<ItemGroup>
 		<ProjectReference Include="..\YSAI.Core\YSAI.Core.csproj" />

+ 1 - 1
src/YSAI.DAQ/YSAI.DaqManage/YSAI.DaqManage.csproj

@@ -7,7 +7,7 @@
   </PropertyGroup>
 	<ItemGroup>
 		<FrameworkReference Include="Microsoft.AspNetCore.App" />
-		<PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+		<PackageReference Include="YSAI.Core" Version="1.0.0.61" />
 	</ItemGroup>
 
 	<!--<ItemGroup>

+ 2 - 2
src/YSAI.DAQ/YSAI.Kafka/YSAI.Kafka.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
 	  <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-	  <Version>1.0.0.26</Version>
+	  <Version>1.0.0.27</Version>
 	  <Authors>Shun</Authors>
 	  <Company>YSAI</Company>
 	  <Product>SCADA</Product>
@@ -14,7 +14,7 @@
 
   <ItemGroup>
     <PackageReference Include="Confluent.Kafka" Version="2.2.0" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.61" />
   </ItemGroup>
 	
 	<!--<ItemGroup>

+ 2 - 2
src/YSAI.DAQ/YSAI.Modbus/YSAI.Modbus.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
 	  <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-	  <Version>1.0.0.25</Version>
+	  <Version>1.0.0.26</Version>
 	  <Authors>Shun</Authors>
 	  <Company>YSAI</Company>
 	  <Product>SCADA</Product>
@@ -15,7 +15,7 @@
 	<ItemGroup>
     <PackageReference Include="NModbus" Version="3.0.80" />
     <PackageReference Include="NModbus.Serial" Version="3.0.80" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.61" />
   </ItemGroup>
 
 	<!--<ItemGroup>

+ 2 - 2
src/YSAI.DAQ/YSAI.Mqtt/YSAI.Mqtt.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
 	  <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-	  <Version>1.0.0.28</Version>
+	  <Version>1.0.0.29</Version>
 	  <Authors>Shun</Authors>
 	  <Company>YSAI</Company>
 	  <Product>SCADA</Product>
@@ -15,7 +15,7 @@
   <ItemGroup>
     <PackageReference Include="MQTTnet" Version="4.3.1.873" />
     <PackageReference Include="MQTTnet.AspNetCore" Version="4.3.1.873" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.61" />
   </ItemGroup>
 
 	<!--<ItemGroup>

+ 26 - 0
src/YSAI.DAQ/YSAI.Netty.Pack/Program.cs

@@ -0,0 +1,26 @@
+using YSAI.Netty.client;
+using YSAI.Unility;
+
+namespace YSAI.Netty.Pack;
+class Program
+{
+    static void Main(string[] args)
+    {
+        string FileDirectory = string.Empty;
+        string[] paths = AppDomain.CurrentDomain.BaseDirectory.Split('\\');
+        for (int i = 0; i < paths.Length - 5; i++)
+        {
+            FileDirectory += $"{paths[i]}//";
+        }
+        FileDirectory += "YSAI.Manage//param";
+        string Name = "YSAI.Netty";
+        string ParamFile = $"{FileDirectory}//{Name}.Param.json";
+        string ParamDetailsFile = $"{FileDirectory}//{Name}.ParamDetails.json";
+        if (!Directory.Exists(FileDirectory))
+        {
+            Directory.CreateDirectory(FileDirectory);
+        }
+        FileTool.StringToFile(ParamFile, new NettyClientData.Basics().ToJson().JsonFormatting());
+        FileTool.StringToFile(ParamDetailsFile, ReflexTool.GetClassAllPropertyData<NettyClientData.Basics>().ToJson().JsonFormatting());
+    }
+}

Файловите разлики са ограничени, защото са твърде много
+ 16 - 0
src/YSAI.DAQ/YSAI.Netty.Pack/YSAI.Netty.Pack.csproj


+ 13 - 0
src/YSAI.DAQ/YSAI.Netty/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>..\YSAI.Publish\Release\net6.0\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+  </PropertyGroup>
+</Project>

+ 1 - 1
src/YSAI.DAQ/YSAI.Netty/YSAI.Netty.csproj

@@ -14,6 +14,6 @@
 	<ItemGroup>
 		<PackageReference Include="DotNetty.Handlers" Version="0.7.5" />
 		<PackageReference Include="DotNetty.Transport" Version="0.7.5" />
-		<PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+		<PackageReference Include="YSAI.Core" Version="1.0.0.61" />
 	</ItemGroup>
 </Project>

+ 11 - 0
src/YSAI.DAQ/YSAI.Netty/client/NettyClientData.cs

@@ -44,6 +44,17 @@ namespace YSAI.Netty.client
             /// </summary>
             [Description("SSL文件密码")]
             public string? SslFilePassword { get; set; }
+
+            /// <summary>
+            /// 任务数量
+            /// </summary>
+            [Description("任务数量")]
+            public int TaskNumber { get; set; } = 5;
+            /// <summary>
+            /// 任务处理间隔(毫秒)
+            /// </summary>
+            [Description("任务处理间隔(毫秒)")]
+            public int TaskHandleInterval { get; set; } = 100;
         }
     }
 }

+ 98 - 23
src/YSAI.DAQ/YSAI.Netty/client/NettyClientOperate.cs

@@ -10,6 +10,7 @@ using System.Security.Cryptography.X509Certificates;
 using YSAI.Core.data;
 using YSAI.Core.@interface;
 using YSAI.Unility;
+using static YSAI.Netty.client.NettyClientOperate;
 
 namespace YSAI.Netty.client
 {
@@ -74,6 +75,15 @@ namespace YSAI.Netty.client
         /// </summary>
         private IChannel Channel;
 
+        /// <summary>
+        /// 任务集合
+        /// </summary>
+        private ConcurrentDictionary<CancellationTokenSource, Task> TaskArray;
+        /// <summary>
+        /// 数据队列
+        /// </summary>
+        private ConcurrentQueue<Info> DataQueue;
+
         /// <summary>
         /// 订阅的主题项容器
         /// </summary>
@@ -121,6 +131,27 @@ namespace YSAI.Netty.client
                 {
                     return Break("Off", false, "未连接");
                 }
+                //任务清空
+                if (TaskArray != null)
+                {
+                    foreach (var item in TaskArray)
+                    {
+                        item.Key.Cancel();
+                    }
+                    foreach (var item in TaskArray)
+                    {
+                        item.Value.Wait();
+                        item.Value.Dispose();
+                    }
+                    TaskArray.Clear();
+                    TaskArray = null;
+                }
+                //队列数据清空
+                if (DataQueue != null)
+                {
+                    DataQueue.Clear();
+                    DataQueue = null;
+                }
                 Communication = null;
                 Group?.ShutdownGracefullyAsync().Wait();
                 Channel.CloseAsync().Wait();
@@ -155,41 +186,69 @@ namespace YSAI.Netty.client
         }
 
         /// <summary>
-        /// 内部消息接收
+        /// 任务处理
         /// </summary>
-        /// <param name="sender"></param>
-        /// <param name="e"></param>
-        protected void OnMe(object? sender, EventResult e)
+        /// <param name="token">任务令牌</param>
+        /// <returns>任务</returns>
+        private Task TaskHandle(CancellationTokenSource token)
         {
-            if (e.State)
+            //起个新线程处理
+            return Task.Factory.StartNew(() =>
             {
-                //收到数据
-                if (SubIoc.Count > 0)
+                while (!token.IsCancellationRequested)
                 {
-                    Info? info = e.RData as Info;
-                    if (info != null && !string.IsNullOrEmpty(info.Msg))
+                    //队列数据
+                    Info? queueData;
+                    while (DataQueue.TryDequeue(out queueData))
                     {
-                        string Con = info.Msg;
-                        string? Terminal = info.Context.Channel.RemoteAddress.ToString();
-                        if (Con.IsJson())
+                        if (queueData != null && !token.IsCancellationRequested)
                         {
-                            M? msg = Con.JsonToObject<M>();
-                            if (SubIoc.ContainsKey(msg.T))
+                            if (!string.IsNullOrEmpty(queueData.Msg))
                             {
-                                string Topic = msg.T;
-                                string Content = msg.C;
-
-                                if (Content.IsJson())
-                                {
-                                    OnEventHandler(this, new EventResult(true, $"{TAG} 接收到主题 ( {Topic} ) 内容 ( {Content} )", "{" + $"\"Topic\":\"{Topic}\",\"Content\":{Content},\"Terminal\":\"{Terminal}\"" + "}", Core.@enum.ResultType.Dynamic));
-                                }
-                                else
+                                string Con = queueData.Msg;
+                                string? Terminal = queueData.Context.Channel.LocalAddress.ToString();
+                                if (Con.IsJson())
                                 {
-                                    OnEventHandler(this, new EventResult(true, $"{TAG} 接收到主题 ( {Topic} ) 内容 ( {Content} )", "{" + $"\"Topic\":\"{Topic}\",\"Content\":\"{Content}\",\"Terminal\":\"{Terminal}\"" + "}", Core.@enum.ResultType.Dynamic));
+                                    M? msg = Con.JsonToObject<M>();
+                                    if (SubIoc.ContainsKey(msg.T))
+                                    {
+                                        string Topic = msg.T;
+                                        string Content = msg.C;
+
+                                        if (Content.IsJson())
+                                        {
+                                            //OnEventHandler(this, new EventResult(true, $"{TAG} 接收到主题 ( {Topic} ) 内容 ( {Content} )", "{" + $"\"Topic\":\"{Topic}\",\"Content\":{Content},\"Terminal\":\"{Terminal}\"" + "}", Core.@enum.ResultType.Dynamic));
+                                            OnEventHandler(this, new EventResult(true, $"{TAG} 接收到主题 ( {Topic} ) 内容 ( {Content} )", "{" + $"\"Topic\":\"{Topic}\",\"Content\":{Content}" + "}", Core.@enum.ResultType.Dynamic));
+                                        }
+                                        else
+                                        {
+                                            //OnEventHandler(this, new EventResult(true, $"{TAG} 接收到主题 ( {Topic} ) 内容 ( {Content} )", "{" + $"\"Topic\":\"{Topic}\",\"Content\":\"{Content}\",\"Terminal\":\"{Terminal}\"" + "}", Core.@enum.ResultType.Dynamic));
+                                            OnEventHandler(this, new EventResult(true, $"{TAG} 接收到主题 ( {Topic} ) 内容 ( {Content} )", "{" + $"\"Topic\":\"{Topic}\",\"Content\":\"{Content}\"" + "}", Core.@enum.ResultType.Dynamic));
+                                        }
+                                    }
                                 }
                             }
                         }
                     }
+                    //队列里面的数据处理完休息一下
+                    Thread.Sleep(basics.TaskHandleInterval);
+                }
+            }, token.Token);
+        }
+
+        /// <summary>
+        /// 内部消息接收
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void OnMe(object? sender, EventResult e)
+        {
+            if (e.State)
+            {
+                //收到数据
+                if (SubIoc.Count > 0)
+                {
+                    DataQueue.Enqueue(e.RData as Info);
                 }
             }
             else
@@ -359,6 +418,22 @@ namespace YSAI.Netty.client
                 {
                     return Break("Subscribe", false, "未连接");
                 }
+                //当队列为空,初始化队列
+                if (DataQueue == null)
+                {
+                    DataQueue = new ConcurrentQueue<Info>();
+                }
+                //任务为空创建任务
+                if (TaskArray == null)
+                {
+                    TaskArray = new ConcurrentDictionary<CancellationTokenSource, Task>();
+                    //创建任务
+                    for (int i = 0; i < basics.TaskNumber; i++)
+                    {
+                        CancellationTokenSource token = new CancellationTokenSource();
+                        TaskArray.TryAdd(token, TaskHandle(token));
+                    }
+                }
                 if (SubIoc.ContainsKey(Topic))
                 {
                     return Break("Subscribe", false, "主题已存在");

+ 115 - 47
src/YSAI.DAQ/YSAI.Netty/service/NettyServiceOperate.cs

@@ -23,7 +23,7 @@ using YSAI.Unility;
 
 namespace YSAI.Netty.service
 {
-    public class NettyServiceOperate: IBaseAbstract, IDisposable
+    public class NettyServiceOperate : IBaseAbstract, IDisposable
     {
         protected override string TAG => "NettyServiceOperate";
 
@@ -105,16 +105,11 @@ namespace YSAI.Netty.service
         /// <param name="e"></param>
         protected void OnMe(object? sender, EventResult e)
         {
+            OnEventHandler(this, e);
             if (!e.State)
             {
-                //出现异常
-                OnEventHandler(this, new EventResult(false, $"服务端异常:{e.Message}"));
                 Off();
             }
-            else
-            {
-                OnEventHandler(this, new EventResult(true, e.Message));
-            }
         }
 
         /// <summary>
@@ -122,6 +117,28 @@ namespace YSAI.Netty.service
         /// </summary>
         public class SecureChatServerHandler : SimpleChannelInboundHandler<string>
         {
+            /// <summary>
+            /// IP处理
+            /// </summary>
+            /// <param name="Ip"></param>
+            /// <returns></returns>
+            private string IpHandle(EndPoint Ip)
+            {
+                //原始数据
+                string ip = string.Empty;
+                string? ip_od = Ip.ToString();
+                if (!string.IsNullOrWhiteSpace(ip_od))
+                {
+                    string[] str = ip_od.Replace("[", "").Replace("]", "").Split(':');
+                    ip = $"{str[3]}:{str[4]}";
+                }
+                return ip;
+            }
+
+            /// <summary>
+            /// 客户端容器
+            /// </summary>
+            private static volatile ConcurrentDictionary<string, IChannel> ClientIoc = new ConcurrentDictionary<string, IChannel>();
             /// <summary>
             /// 消息事件
             /// </summary>
@@ -152,34 +169,12 @@ namespace YSAI.Netty.service
                         if (ChannelGroup == null)
                         {
                             g = ChannelGroup = new DefaultChannelGroup(contex.Executor);
-                            MessageEvent?.Invoke(this, new EventResult(true, $"{contex.Channel.RemoteAddress} 激活了通道"));
                         }
                     }
                 }
-                g.Add(contex.Channel);
-            }
-            public override Task DisconnectAsync(IChannelHandlerContext context)
-            {
-                MessageEvent?.Invoke(this, new EventResult(true, $"{context.Channel.RemoteAddress} 释放并断开连接"));
-                return base.DisconnectAsync(context);
-            }
-            /// <summary>
-            /// 通道关闭
-            /// </summary>
-            /// <returns></returns>
-            public override Task CloseAsync(IChannelHandlerContext context)
-            {
-                MessageEvent?.Invoke(this, new EventResult(true, $"{context.Channel.RemoteAddress} 关闭连接"));
-                return base.CloseAsync(context);
-            }
-            /// <summary>
-            /// 通道连接
-            /// </summary>
-            /// <returns></returns>
-            public override Task ConnectAsync(IChannelHandlerContext context, EndPoint remoteAddress, EndPoint localAddress)
-            {
-                MessageEvent?.Invoke(this, new EventResult(true, $"{remoteAddress} 与 {localAddress} 建立连接 "));
-                return base.ConnectAsync(context, remoteAddress, localAddress);
+                string ip = IpHandle(contex.Channel.RemoteAddress);
+                ClientIoc.AddOrUpdate(ip, contex.Channel, (k, v) => contex.Channel);
+                MessageEvent?.Invoke(this, new EventResult(true, $"{ip} 激活了通道",ip));
             }
 
             /// <summary>
@@ -216,8 +211,12 @@ namespace YSAI.Netty.service
             /// <param name="e">异常信息</param>
             public override void ExceptionCaught(IChannelHandlerContext contex, Exception ex)
             {
+                //移除IP
+                string ip = IpHandle(contex.Channel.RemoteAddress);
+                ClientIoc.Remove(ip, out _);
+
                 //消息抛出
-                MessageEvent?.Invoke(this, new EventResult(false, ex.Message));
+                MessageEvent?.Invoke(this, new EventResult(false, $"{contex.Channel.RemoteAddress} {ex.Message}", ip));
 
                 //通道关闭
                 contex.CloseAsync();
@@ -225,16 +224,33 @@ namespace YSAI.Netty.service
             /// <summary>
             /// 数据发送
             /// </summary>
-            /// <param name="Data"></param>
-            public static OperateResult Send(string Data)
+            /// <param name="Data">数据</param>
+            /// <param name="IpPort">IP端口</param>
+            /// <returns></returns>
+            public static OperateResult Send(string Data, string? IpPort = null)
             {
                 try
                 {
-                    if (ChannelGroup != null && ChannelGroup.Count > 0)
+                    if (ChannelGroup != null)
                     {
-                        //群发
-                        ChannelGroup.WriteAndFlushAsync(string.Format("{0}\n", Data)).Wait();
-                        return new OperateResult(true, string.Empty, 1);
+                        if (IpPort != null)
+                        {
+                            if (ClientIoc.ContainsKey(IpPort))
+                            {
+                                ClientIoc[IpPort].WriteAndFlushAsync(string.Format("{0}\n", Data));
+                                return new OperateResult(true, string.Empty, 1);
+                            }
+                            else
+                            {
+                                return new OperateResult(false, $"{IpPort} 终端不存在", 1);
+                            }
+                        }
+                        else
+                        {
+                            //群发
+                            ChannelGroup.WriteAndFlushAsync(string.Format("{0}\n", Data));
+                            return new OperateResult(true, string.Empty, 1);
+                        }
                     }
                     else
                     {
@@ -273,7 +289,7 @@ namespace YSAI.Netty.service
             {
                 if (Channel != null)
                 {
-                    return Break("On", false, "已连接");
+                    return Break("On", false, "已启动");
                 }
                 //证书
                 X509Certificate2? Cert = null;
@@ -304,7 +320,8 @@ namespace YSAI.Netty.service
                 .Channel<TcpServerSocketChannel>()  //创建一个通道
                 .Option(ChannelOption.SoBacklog, 128)   //TCP节点布局
                 .Handler(new LoggingHandler(LogLevel.INFO)) //日志
-                .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel => { //处理
+                .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
+                { //处理
                     IChannelPipeline pipeline = channel.Pipeline;
                     if (Cert != null)
                     {
@@ -345,7 +362,7 @@ namespace YSAI.Netty.service
             {
                 if (Channel == null)
                 {
-                    return Break("Off", false, "未连接");
+                    return Break("Off", false, "未启动");
                 }
                 Communication = null;
                 ClientGroup?.ShutdownGracefullyAsync().Wait();
@@ -374,18 +391,19 @@ namespace YSAI.Netty.service
         /// 群发数据
         /// </summary>
         /// <param name="Data">数据</param>
+        /// <param name="IpPort">IP端口</param>
         /// <returns></returns>
-        public OperateResult Send(string Data)
+        public OperateResult Send(string Data, string? IpPort = null)
         {
             Depart("Send");
             try
             {
                 if (Channel == null)
                 {
-                    return Break("Send", false, "未连接");
+                    return Break("Send", false, "未启动");
                 }
                 //等待发送完成
-               return SecureChatServerHandler.Send(Data);
+                return SecureChatServerHandler.Send(Data, IpPort);
             }
             catch (Exception ex)
             {
@@ -397,10 +415,60 @@ namespace YSAI.Netty.service
         /// 群发数据
         /// </summary>
         /// <param name="Data">数据</param>
+        /// <param name="IpPort">IP端口</param>
+        /// <returns></returns>
+        public Task<OperateResult> SendAsync(string Data, string? IpPort = null)
+        {
+            return Task.Run(() => Send(Data, IpPort));
+        }
+
+        /// <summary>
+        /// 群发数据
+        /// </summary>
+        /// <param name="Topic">主题</param>
+        /// <param name="Content">内容</param>
+        /// <param name="IpPort">IP端口</param>
+        /// <returns></returns>
+        public OperateResult Send(string Topic, string Content, string? IpPort = null)
+        {
+            Depart("Send");
+            try
+            {
+                if (Channel == null)
+                {
+                    return Break("Send", false, "未启动");
+                }
+
+                //内部消息组织
+                string msg = string.Empty;
+                if (Content.IsJson())
+                {
+                    msg = "{" + string.Format("\"T\":\"{0}\",\"C\":{1}", Topic, Content) + "}\r\n";
+                }
+                else
+                {
+                    msg = "{" + string.Format("\"T\":\"{0}\",\"C\":\"{1}\"", Topic, Content) + "}\r\n";
+                }
+
+                //等待发送完成
+                return SecureChatServerHandler.Send(msg, IpPort);
+            }
+            catch (Exception ex)
+            {
+                return Break("Send", false, ex.Message, Exception: ex);
+            }
+        }
+
+        /// <summary>
+        /// 群发数据
+        /// </summary>
+        /// <param name="Topic">主题</param>
+        /// <param name="Content">内容</param>
+        /// <param name="IpPort">IP端口</param>
         /// <returns></returns>
-        public Task<OperateResult> SendAsync(string Data)
+        public Task<OperateResult> SendAsync(string Topic, string Content, string? IpPort = null)
         {
-            return Task.Run(()=> Send(Data));
+            return Task.Run(() => Send(Topic, Content, IpPort));
         }
     }
 }

+ 2 - 2
src/YSAI.DAQ/YSAI.Opc/YSAI.Opc.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
 	  <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-	  <Version>1.0.0.35</Version>
+	  <Version>1.0.0.36</Version>
 	  <Authors>Shun</Authors>
 	  <Company>YSAI</Company>
 	  <Product>SCADA</Product>
@@ -13,7 +13,7 @@
   </PropertyGroup>
   <ItemGroup>
     <PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.4.372.56" />
-	<PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+	<PackageReference Include="YSAI.Core" Version="1.0.0.61" />
   </ItemGroup>
 
 

+ 2 - 2
src/YSAI.DAQ/YSAI.RabbitMQ/YSAI.RabbitMQ.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
 	  <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-	  <Version>1.0.0.27</Version>
+	  <Version>1.0.0.28</Version>
 	  <Authors>Shun</Authors>
 	  <Company>YSAI</Company>
 	  <Product>SCADA</Product>
@@ -14,7 +14,7 @@
 
   <ItemGroup>
     <PackageReference Include="RabbitMQ.Client" Version="6.6.0" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.61" />
   </ItemGroup>
 
   <ItemGroup>

+ 1 - 1
src/YSAI.DAQ/YSAI.RelayManage/YSAI.RelayManage.csproj

@@ -9,7 +9,7 @@
 	<ItemGroup>
 		<PackageReference Include="RabbitMQ.Client" Version="6.6.0" />
 		<PackageReference Include="Confluent.Kafka" Version="2.2.0" />
-		<PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+		<PackageReference Include="YSAI.Core" Version="1.0.0.61" />
 		<FrameworkReference Include="Microsoft.AspNetCore.App" />
 	</ItemGroup>
 

+ 2 - 2
src/YSAI.DAQ/YSAI.S7/YSAI.S7.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
 	  <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-	  <Version>1.0.0.24</Version>
+	  <Version>1.0.0.25</Version>
 	  <Authors>Shun</Authors>
 	  <Company>YSAI</Company>
 	  <Product>SCADA</Product>
@@ -14,7 +14,7 @@
 
 	<ItemGroup>
     <PackageReference Include="S7netplus" Version="0.20.0" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.61" />
   </ItemGroup>
 
 	<!--<ItemGroup>

+ 11 - 4
src/YSAI.DAQ/YSAI.Test.All/Program.cs

@@ -1,4 +1,5 @@
-using YSAI.Core.data;
+using System.Net;
+using YSAI.Core.data;
 using YSAI.Log;
 using YSAI.Netty.client;
 using YSAI.Netty.service;
@@ -11,6 +12,10 @@ NettyServiceOperate nettyServiceOperate = NettyServiceOperate.Instance(new Netty
 });
 
 Console.WriteLine(nettyServiceOperate.On().ToJson());
+nettyServiceOperate.OnEvent += delegate (object? sender, EventResult e)
+{
+    LogHelper.Info(e.ToJson().JsonFormatting());
+};
 
 
 //转发协议
@@ -44,20 +49,22 @@ LogHelper.Info(result.ToJson().JsonFormatting());
 
 while (true)
 {
+    Console.WriteLine("请输入端口:");
+   string port= Console.ReadLine();
     for (int i = 0; i < 2; i++)
     {
         if (i == 0)
         {
             //生产
-            operate1.Produce("测试", new Random().NextDouble().ToString());
+            //operate1.Produce("测试", new Random().NextDouble().ToString());
         }
         else
         {
+            IPEndPoint endPoint=new IPEndPoint(IPAddress.Parse("127.0.0.1"), int.Parse(port));
             //生产
-            nettyServiceOperate.Send("测试");
+            Console.WriteLine(nettyServiceOperate.Send("测试", "啊啊啊啊", endPoint.ToString()).ToJson().JsonFormatting());
         }
     }
-   
 }
 
 

+ 1 - 1
src/YSAI.DAQ/YSAI.Test/YSAI.Test.csproj

@@ -17,7 +17,7 @@
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
-	<PackageReference Include="YSAI.Core" Version="1.0.0.60" />
+	<PackageReference Include="YSAI.Core" Version="1.0.0.61" />
   </ItemGroup>
 
   <ItemGroup>