Compare commits
	
		
			67 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | e7dfdd4031 | ||
|   | b2dd7b6364 | ||
|   | 9bd6d9abbf | ||
|   | cd14428fea | ||
|   | 19d9f03c2b | ||
|   | 0d57e72bbf | ||
|   | 329516a61b | ||
|   | d566869589 | ||
|   | 9cb8d8e6c7 | ||
|   | 9de3c57e5d | ||
|   | f32ff92b0b | ||
|   | 88d71e271e | ||
|   | fd9c14612a | ||
|   | e26e5a160f | ||
|   | b836bfed22 | ||
|   | a4b598c6d0 | ||
|   | c9ab755839 | ||
|   | 9920edba53 | ||
|   | 12bd7280d1 | ||
|   | d30ea7f63b | ||
|   | ebd3390db6 | ||
|   | 9a374a9ebc | ||
|   | b1bc22cb08 | ||
|   | 4930d53890 | ||
|   | c31327b5bc | ||
|   | 3f2aa1f1e1 | ||
|   | 6e78c00a96 | ||
|   | c27dde085e | ||
|   | d26cc308c0 | ||
|   | fb1efdf290 | ||
|   | 3c99f2a472 | ||
|   | affe9a44e0 | ||
|   | 43730fa519 | ||
|   | d39aa22b09 | ||
|   | e232a6b6ea | ||
|   | 71ebb36fe9 | ||
|   | 78a0b86327 | ||
|   | 2636c16a97 | ||
|   | fd77c0242d | ||
|   | e74819a900 | ||
|   | 9b7f696c9b | ||
|   | 0230d614e7 | ||
|   | 252d99ad78 | ||
|   | 1ffc200350 | ||
|   | 807d89b2b2 | ||
|   | 4013afa1f1 | ||
|   | a580927ceb | ||
|   | bf2cf52034 | ||
|   | 81bb8b7c31 | ||
|   | a825007fb5 | ||
|   | 988124d96a | ||
|   | f0de815296 | ||
|   | 0e2d58c887 | ||
|   | b155382626 | ||
|   | f362d740af | ||
|   | 4a85e31a4f | ||
|   | 302c270ad5 | ||
|   | 3c1517d0f3 | ||
|   | f9fb222044 | ||
|   | e8edc02ba3 | ||
|   | 95a44e3053 | ||
|   | 74a9fe9a87 | ||
|   | 4d03f9ea1a | ||
|   | 67c96ca991 | ||
|   | 88fb793c68 | ||
|   | d6d02d8cc5 | ||
|   | c5a3f8e2e3 | 
| @@ -5,3 +5,99 @@ dotnet_diagnostic.CA1848.severity = none | ||||
|  | ||||
| # CA2254: 模板应为静态表达式 | ||||
| dotnet_diagnostic.CA2254.severity = suggestion | ||||
|  | ||||
| [*.cs] | ||||
| #### 命名样式 #### | ||||
|  | ||||
| # 命名规则 | ||||
|  | ||||
| dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion | ||||
| dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface | ||||
| dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i | ||||
|  | ||||
| dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion | ||||
| dotnet_naming_rule.types_should_be_pascal_case.symbols = types | ||||
| dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case | ||||
|  | ||||
| dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion | ||||
| dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members | ||||
| dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case | ||||
|  | ||||
| # 符号规范 | ||||
|  | ||||
| dotnet_naming_symbols.interface.applicable_kinds = interface | ||||
| dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected | ||||
| dotnet_naming_symbols.interface.required_modifiers =  | ||||
|  | ||||
| dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum | ||||
| dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected | ||||
| dotnet_naming_symbols.types.required_modifiers =  | ||||
|  | ||||
| dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method | ||||
| dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected | ||||
| dotnet_naming_symbols.non_field_members.required_modifiers =  | ||||
|  | ||||
| # 命名样式 | ||||
|  | ||||
| dotnet_naming_style.begins_with_i.required_prefix = I | ||||
| dotnet_naming_style.begins_with_i.required_suffix =  | ||||
| dotnet_naming_style.begins_with_i.word_separator =  | ||||
| dotnet_naming_style.begins_with_i.capitalization = pascal_case | ||||
|  | ||||
| dotnet_naming_style.pascal_case.required_prefix =  | ||||
| dotnet_naming_style.pascal_case.required_suffix =  | ||||
| dotnet_naming_style.pascal_case.word_separator =  | ||||
| dotnet_naming_style.pascal_case.capitalization = pascal_case | ||||
|  | ||||
| dotnet_naming_style.pascal_case.required_prefix =  | ||||
| dotnet_naming_style.pascal_case.required_suffix =  | ||||
| dotnet_naming_style.pascal_case.word_separator =  | ||||
| dotnet_naming_style.pascal_case.capitalization = pascal_case | ||||
|  | ||||
| [*.vb] | ||||
| #### 命名样式 #### | ||||
|  | ||||
| # 命名规则 | ||||
|  | ||||
| dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion | ||||
| dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface | ||||
| dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始 | ||||
|  | ||||
| dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion | ||||
| dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型 | ||||
| dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法 | ||||
|  | ||||
| dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion | ||||
| dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员 | ||||
| dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法 | ||||
|  | ||||
| # 符号规范 | ||||
|  | ||||
| dotnet_naming_symbols.interface.applicable_kinds = interface | ||||
| dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected | ||||
| dotnet_naming_symbols.interface.required_modifiers =  | ||||
|  | ||||
| dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum | ||||
| dotnet_naming_symbols.类型.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected | ||||
| dotnet_naming_symbols.类型.required_modifiers =  | ||||
|  | ||||
| dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method | ||||
| dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected | ||||
| dotnet_naming_symbols.非字段成员.required_modifiers =  | ||||
|  | ||||
| # 命名样式 | ||||
|  | ||||
| dotnet_naming_style.以_i_开始.required_prefix = I | ||||
| dotnet_naming_style.以_i_开始.required_suffix =  | ||||
| dotnet_naming_style.以_i_开始.word_separator =  | ||||
| dotnet_naming_style.以_i_开始.capitalization = pascal_case | ||||
|  | ||||
| dotnet_naming_style.帕斯卡拼写法.required_prefix =  | ||||
| dotnet_naming_style.帕斯卡拼写法.required_suffix =  | ||||
| dotnet_naming_style.帕斯卡拼写法.word_separator =  | ||||
| dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case | ||||
|  | ||||
| dotnet_naming_style.帕斯卡拼写法.required_prefix =  | ||||
| dotnet_naming_style.帕斯卡拼写法.required_suffix =  | ||||
| dotnet_naming_style.帕斯卡拼写法.word_separator =  | ||||
| dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <Project> | ||||
| 	<PropertyGroup> | ||||
| 		<Version>3.0.0.13</Version> | ||||
| 		<Version>3.0.0.25</Version> | ||||
| 		<LangVersion>latest</LangVersion> | ||||
| 		<TargetFrameworks>net6.0;net7.0</TargetFrameworks> | ||||
| 		<Authors>Diego</Authors> | ||||
|   | ||||
| @@ -101,7 +101,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             Messages.Add((LogLevel.Error, | ||||
|             $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 错误:{ex.Message}")); | ||||
|             $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 错误:{ex}")); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| @@ -126,7 +126,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             Messages.Add((LogLevel.Error, | ||||
|             $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 写入前失败:{ex.Message}")); | ||||
|             $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 写入前失败:{ex}")); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -49,7 +49,7 @@ public partial class DriverDebugUIPage : DriverDebugUIBase | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + ex.Message)); | ||||
|                     Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + ex)); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| #region copyright | ||||
| #region copyright | ||||
| //------------------------------------------------------------------------------ | ||||
| //  <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ||||
| //  <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>룩<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ||||
| //  Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD>鼰<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> | ||||
| //  GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway | ||||
| //  GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway | ||||
| //  ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ | ||||
| //  QQȺ<EFBFBD><EFBFBD>605534569 | ||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||
| //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||
| //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||
| //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||
| //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||
| //  QQ群:605534569 | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| @@ -26,7 +26,7 @@ public partial class MainLayout | ||||
| [ | ||||
|   { | ||||
|     "Href": "/index", | ||||
|     "Title": "<EFBFBD><EFBFBD>ҳ" | ||||
|     "Title": "首页" | ||||
|   }, | ||||
|   { | ||||
|     "Title": "Modbus", | ||||
|   | ||||
| @@ -56,10 +56,10 @@ | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\MqttRpcNameVaueWithId.cs" Link="Pages\Mqtt\MqttRpcNameVaueWithId.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor.cs" Link="Pages\Mqtt\MqttClientDebugPage.razor.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor.cs" Link="Pages\Mqtt\MqttClientPage.razor.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\PrivateLogger.cs" Link="Pages\Mqtt\PrivateLogger.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClient.cs" Link="Pages\Mqtt\MqttRpcClient.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClientExtensions.cs" Link="Pages\Mqtt\MqttRpcClientExtensions.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcTopicPair.cs" Link="Pages\Mqtt\MqttRpcTopicPair.cs" /> | ||||
| 		<Compile Include="..\..\Web\ThingsGateway.Gateway.Application\Workers\ManageGateway\MqttLoggerExtensions.cs" Link="Pages\Mqtt\MqttLoggerExtensions.cs" /> | ||||
| 		<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor" Link="Pages\DLT645\DLT645_2007DebugPage.razor" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor.cs" /> | ||||
| 		<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor" /> | ||||
| @@ -115,20 +115,20 @@ | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
| 	<ItemGroup > | ||||
| 		<PackageReference Include="ThingsGateway.Foundation.Adapter.DLT645" Version="*" /> | ||||
| 	<ItemGroup> | ||||
| 		<!--<PackageReference Include="ThingsGateway.Foundation.Adapter.DLT645" Version="*" /> | ||||
| 		<PackageReference Include="ThingsGateway.Foundation.Adapter.Modbus" Version="*" /> | ||||
| 		<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCDA" Version="*" /> | ||||
| 		<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCUA" Version="*" /> | ||||
| 		<PackageReference Include="ThingsGateway.Foundation.Adapter.Siemens" Version="*" /> | ||||
| 		<!--<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.DLT645\ThingsGateway.Foundation.Adapter.DLT645.csproj" /> | ||||
| 		<PackageReference Include="ThingsGateway.Foundation.Adapter.Siemens" Version="*" />--> | ||||
| 		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.DLT645\ThingsGateway.Foundation.Adapter.DLT645.csproj" /> | ||||
| 		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj" /> | ||||
| 		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCDA\ThingsGateway.Foundation.Adapter.OPCDA.csproj" /> | ||||
| 		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj" /> | ||||
| 		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj" />--> | ||||
| 		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj" /> | ||||
|  | ||||
| 	</ItemGroup> | ||||
| 	<ItemGroup > | ||||
| 	<ItemGroup> | ||||
| 		<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <Project> | ||||
| 	<PropertyGroup> | ||||
| 		<Version>3.0.0.13</Version> | ||||
| 		<Version>3.0.0.25</Version> | ||||
| 		<GenerateDocumentationFile>True</GenerateDocumentationFile> | ||||
| 		<LangVersion>latest</LangVersion> | ||||
| 		<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks> | ||||
|   | ||||
| @@ -444,7 +444,7 @@ public class DLT645_2007 : ReadWriteDevicesSerialSessionBase | ||||
|  | ||||
|             if (Station.IsNullOrEmpty()) Station = string.Empty; | ||||
|             if (Station.Length < 12) Station = Station.PadLeft(12, '0'); | ||||
|             string str = $"04000C{(level + 1):D2}"; | ||||
|             string str = $"04000C{level + 1:D2}"; | ||||
|  | ||||
|             var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WritePassword, | ||||
|                 str.ByHexStringToBytes().Reverse().ToArray() | ||||
|   | ||||
| @@ -92,15 +92,15 @@ public class DLT645_2007Address : DeviceAddressBase | ||||
|         StringBuilder stringGeter = new(); | ||||
|         if (Station.Length > 0) | ||||
|         { | ||||
|             stringGeter.Append("s=" + Station.Reverse().ToArray().ToHexString() + ";"); | ||||
|             stringGeter.Append($"s={Station.Reverse().ToArray().ToHexString()};"); | ||||
|         } | ||||
|         if (DataId.Length > 0) | ||||
|         { | ||||
|             stringGeter.Append(DataId.Reverse().ToArray().ToHexString() + ";"); | ||||
|             stringGeter.Append($"{DataId.Reverse().ToArray().ToHexString()};"); | ||||
|         } | ||||
|         if (!Reverse) | ||||
|         { | ||||
|             stringGeter.Append("s=" + Reverse.ToString() + ";"); | ||||
|             stringGeter.Append($"s={Reverse.ToString()};"); | ||||
|         } | ||||
|         return stringGeter.ToString(); | ||||
|     } | ||||
|   | ||||
| @@ -134,7 +134,7 @@ public class DLT645_2007DataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter | ||||
|  | ||||
|             if ((response[headCodeIndex + 8] != send[sendHeadCodeIndex + 8] + 0x80))//控制码不符合时,返回错误 | ||||
|             { | ||||
|                 request.Message = "返回控制码:" + $"0x{response[headCodeIndex + 8]:X2},请求控制码:" + $"0x{send[sendHeadCodeIndex + 8]:X2},不符合规则"; | ||||
|                 request.Message = $"返回控制码:0x{response[headCodeIndex + 8]:X2},请求控制码:0x{send[sendHeadCodeIndex + 8]:X2},不符合规则"; | ||||
|                 request.ErrorCode = 999; | ||||
|                 return FilterResult.Success; | ||||
|             } | ||||
| @@ -146,7 +146,7 @@ public class DLT645_2007DataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter | ||||
|             { | ||||
|                 byte byte1 = (byte)(response[headCodeIndex + 10] - 0x33); | ||||
|                 var error = DLT645Helper.Get2007ErrorMessage(byte1); | ||||
|                 request.Message = "异常控制码:" + $"0x{response[headCodeIndex + 8]:X2},错误信息:{error}"; | ||||
|                 request.Message = $"异常控制码:0x{response[headCodeIndex + 8]:X2},错误信息:{error}"; | ||||
|                 request.ErrorCode = 999; | ||||
|                 return FilterResult.Success; | ||||
|             } | ||||
|   | ||||
| @@ -147,15 +147,15 @@ public class ModbusAddress : DeviceAddressBase | ||||
|         StringBuilder stringGeter = new(); | ||||
|         if (Station > 0) | ||||
|         { | ||||
|             stringGeter.Append("s=" + Station.ToString() + ";"); | ||||
|             stringGeter.Append($"s={Station.ToString()};"); | ||||
|         } | ||||
|         if (WriteFunction > 0) | ||||
|         { | ||||
|             stringGeter.Append("w=" + WriteFunction.ToString() + ";"); | ||||
|             stringGeter.Append($"w={WriteFunction.ToString()};"); | ||||
|         } | ||||
|         if (!string.IsNullOrEmpty(SocketId)) | ||||
|         { | ||||
|             stringGeter.Append("id=" + SocketId + ";"); | ||||
|             stringGeter.Append($"id={SocketId};"); | ||||
|         } | ||||
|         stringGeter.Append(GetFunctionString(ReadFunction) + (AddressStart + 1).ToString()); | ||||
|         return stringGeter.ToString(); | ||||
|   | ||||
| @@ -117,7 +117,7 @@ internal class ModbusHelper | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[], FilterResult>(ex.Message) { Content2 = FilterResult.Success }; | ||||
|             return new OperResult<byte[], FilterResult>(ex) { Content2 = FilterResult.Success }; | ||||
|         } | ||||
|     } | ||||
|     /// <summary> | ||||
| @@ -165,7 +165,7 @@ internal class ModbusHelper | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex.Message); | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|     } | ||||
|     /// <summary> | ||||
| @@ -185,7 +185,7 @@ internal class ModbusHelper | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex.Message); | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -207,7 +207,7 @@ internal class ModbusHelper | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex.Message); | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|     } | ||||
|     /// <summary> | ||||
| @@ -244,7 +244,7 @@ internal class ModbusHelper | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex.Message); | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -296,7 +296,7 @@ internal class ModbusHelper | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex.Message); | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -101,62 +101,76 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase | ||||
|         return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     EasyLock easyLock = new(); | ||||
|  | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         ModbusAddress mAddress; | ||||
|         try | ||||
|         { | ||||
|             mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|         if (MulStation) | ||||
|         { | ||||
|             Init(mAddress); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (Station != mAddress.Station) | ||||
|             easyLock.Wait(); | ||||
|  | ||||
|             ModbusAddress mAddress; | ||||
|             try | ||||
|             { | ||||
|                 return new OperResult<byte[]>("地址错误"); | ||||
|                 mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|             } | ||||
|             Init(mAddress); | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 return new OperResult<byte[]>(ex); | ||||
|             } | ||||
|             if (MulStation) | ||||
|             { | ||||
|                 Init(mAddress); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (Station != mAddress.Station) | ||||
|                 { | ||||
|                     return new OperResult<byte[]>("地址错误"); | ||||
|                 } | ||||
|                 Init(mAddress); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station]; | ||||
|             int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength; | ||||
|             switch (mAddress.ReadFunction) | ||||
|             { | ||||
|                 case 1: | ||||
|                     byte[] bytes0 = new byte[len]; | ||||
|                     ModbusServer01ByteBlock.Pos = mAddress.AddressStart; | ||||
|                     ModbusServer01ByteBlock.Read(bytes0); | ||||
|                     return OperResult.CreateSuccessResult(bytes0); | ||||
|                 case 2: | ||||
|                     byte[] bytes1 = new byte[len]; | ||||
|                     ModbusServer02ByteBlock.Pos = mAddress.AddressStart; | ||||
|                     ModbusServer02ByteBlock.Read(bytes1); | ||||
|                     return OperResult.CreateSuccessResult(bytes1); | ||||
|                 case 3: | ||||
|  | ||||
|                     byte[] bytes3 = new byte[len]; | ||||
|                     ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                     ModbusServer03ByteBlock.Read(bytes3); | ||||
|                     return OperResult.CreateSuccessResult(bytes3); | ||||
|                 case 4: | ||||
|                     byte[] bytes4 = new byte[len]; | ||||
|                     ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                     ModbusServer04ByteBlock.Read(bytes4); | ||||
|                     return OperResult.CreateSuccessResult(bytes4); | ||||
|             } | ||||
|             return new OperResult<byte[]>("功能码错误"); | ||||
|         } | ||||
|  | ||||
|         var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station]; | ||||
|         int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength; | ||||
|         switch (mAddress.ReadFunction) | ||||
|         finally | ||||
|         { | ||||
|             case 1: | ||||
|                 byte[] bytes0 = new byte[len]; | ||||
|                 ModbusServer01ByteBlock.Pos = mAddress.AddressStart; | ||||
|                 ModbusServer01ByteBlock.Read(bytes0); | ||||
|                 return OperResult.CreateSuccessResult(bytes0); | ||||
|             case 2: | ||||
|                 byte[] bytes1 = new byte[len]; | ||||
|                 ModbusServer02ByteBlock.Pos = mAddress.AddressStart; | ||||
|                 ModbusServer02ByteBlock.Read(bytes1); | ||||
|                 return OperResult.CreateSuccessResult(bytes1); | ||||
|             case 3: | ||||
|  | ||||
|                 byte[] bytes3 = new byte[len]; | ||||
|                 ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                 ModbusServer03ByteBlock.Read(bytes3); | ||||
|                 return OperResult.CreateSuccessResult(bytes3); | ||||
|             case 4: | ||||
|                 byte[] bytes4 = new byte[len]; | ||||
|                 ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                 ModbusServer04ByteBlock.Read(bytes4); | ||||
|                 return OperResult.CreateSuccessResult(bytes4); | ||||
|             easyLock.Release(); | ||||
|         } | ||||
|         return new OperResult<byte[]>("功能码错误"); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
| @@ -173,87 +187,108 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase | ||||
|         SerialSession.SetDataHandlingAdapter(dataHandleAdapter); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         ModbusAddress mAddress; | ||||
|         try | ||||
|         { | ||||
|             mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult(ex); | ||||
|         } | ||||
|         if (MulStation) | ||||
|         { | ||||
|             Init(mAddress); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (Station != mAddress.Station) | ||||
|             easyLock.Wait(); | ||||
|             ModbusAddress mAddress; | ||||
|             try | ||||
|             { | ||||
|                 return new OperResult("地址错误"); | ||||
|                 mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|             } | ||||
|             Init(mAddress); | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 return new OperResult(ex); | ||||
|             } | ||||
|             if (MulStation) | ||||
|             { | ||||
|                 Init(mAddress); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (Station != mAddress.Station) | ||||
|                 { | ||||
|                     return new OperResult("地址错误"); | ||||
|                 } | ||||
|                 Init(mAddress); | ||||
|             } | ||||
|             var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station]; | ||||
|             switch (mAddress.ReadFunction) | ||||
|             { | ||||
|                 case 3: | ||||
|                     ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                     ModbusServer03ByteBlock.Write(value); | ||||
|                     return OperResult.CreateSuccessResult(); | ||||
|                 case 4: | ||||
|                     ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                     ModbusServer04ByteBlock.Write(value); | ||||
|                     return OperResult.CreateSuccessResult(); | ||||
|             } | ||||
|             return new OperResult("功能码错误"); | ||||
|  | ||||
|         } | ||||
|         var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station]; | ||||
|         switch (mAddress.ReadFunction) | ||||
|         finally | ||||
|         { | ||||
|             case 3: | ||||
|                 ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                 ModbusServer03ByteBlock.Write(value); | ||||
|                 return OperResult.CreateSuccessResult(); | ||||
|             case 4: | ||||
|                 ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                 ModbusServer04ByteBlock.Write(value); | ||||
|                 return OperResult.CreateSuccessResult(); | ||||
|  | ||||
|             easyLock.Release(); | ||||
|         } | ||||
|         return new OperResult("功能码错误"); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         ModbusAddress mAddress; | ||||
|         try | ||||
|         { | ||||
|             mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return (new OperResult(ex)); | ||||
|         } | ||||
|         if (MulStation) | ||||
|         { | ||||
|             Init(mAddress); | ||||
|  | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (Station != mAddress.Station) | ||||
|             easyLock.Wait(); | ||||
|             ModbusAddress mAddress; | ||||
|             try | ||||
|             { | ||||
|                 return (new OperResult("地址错误")); | ||||
|                 mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|             } | ||||
|             Init(mAddress); | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 return (new OperResult(ex)); | ||||
|             } | ||||
|             if (MulStation) | ||||
|             { | ||||
|                 Init(mAddress); | ||||
|  | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (Station != mAddress.Station) | ||||
|                 { | ||||
|                     return (new OperResult("地址错误")); | ||||
|                 } | ||||
|                 Init(mAddress); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station]; | ||||
|             switch (mAddress.ReadFunction) | ||||
|             { | ||||
|                 case 1: | ||||
|                     ModbusServer01ByteBlock.Pos = mAddress.AddressStart; | ||||
|                     ModbusServer01ByteBlock.Write(value.BoolArrayToByte()); | ||||
|                     return (OperResult.CreateSuccessResult()); | ||||
|                 case 2: | ||||
|                     ModbusServer02ByteBlock.Pos = mAddress.AddressStart; | ||||
|                     ModbusServer02ByteBlock.Write(value.BoolArrayToByte()); | ||||
|                     return (OperResult.CreateSuccessResult()); | ||||
|             } | ||||
|             return new OperResult("功能码错误"); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station]; | ||||
|         switch (mAddress.ReadFunction) | ||||
|         finally | ||||
|         { | ||||
|             case 1: | ||||
|                 ModbusServer01ByteBlock.Pos = mAddress.AddressStart; | ||||
|                 ModbusServer01ByteBlock.Write(value.BoolArrayToByte()); | ||||
|                 return (OperResult.CreateSuccessResult()); | ||||
|             case 2: | ||||
|                 ModbusServer02ByteBlock.Pos = mAddress.AddressStart; | ||||
|                 ModbusServer02ByteBlock.Write(value.BoolArrayToByte()); | ||||
|                 return (OperResult.CreateSuccessResult()); | ||||
|  | ||||
|             easyLock.Release(); | ||||
|         } | ||||
|         return new OperResult("功能码错误"); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
| @@ -409,13 +444,9 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase | ||||
|  | ||||
|     private void Init(ModbusAddress mAddress) | ||||
|     { | ||||
|         if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128))) | ||||
|             ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128); | ||||
|         if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128))) | ||||
|             ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128); | ||||
|         if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128))) | ||||
|             ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128); | ||||
|         if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128))) | ||||
|             ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128); | ||||
|         ModbusServer01ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128)); | ||||
|         ModbusServer02ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128)); | ||||
|         ModbusServer03ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128)); | ||||
|         ModbusServer04ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -57,7 +57,7 @@ public class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesTcpDataHandle | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex.Message); | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -186,7 +186,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase | ||||
|                 var item = commandResult.Content; | ||||
|                 if (FrameTime != 0) | ||||
|                     Thread.Sleep(FrameTime); | ||||
|                 var WaitingClientEx = client.GetWaitingClient(new() { ThrowBreakException = true }); | ||||
|                 var WaitingClientEx = client.CreateWaitingClient(new() { }); | ||||
|                 var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken); | ||||
|                 return (MessageBase)result.RequestInfo; | ||||
|             } | ||||
| @@ -213,7 +213,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase | ||||
|  | ||||
|                 var item = commandResult.Content; | ||||
|                 await Task.Delay(FrameTime, cancellationToken); | ||||
|                 var WaitingClientEx = client.GetWaitingClient(new() { ThrowBreakException = true }); | ||||
|                 var WaitingClientEx = client.CreateWaitingClient(new() { }); | ||||
|                 var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken); | ||||
|                 return (MessageBase)result.RequestInfo; | ||||
|             } | ||||
|   | ||||
| @@ -104,62 +104,75 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase | ||||
|         return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     EasyLock easyLock = new(); | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         ModbusAddress mAddress; | ||||
|         try | ||||
|         { | ||||
|             mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|         if (MulStation) | ||||
|         { | ||||
|             Init(mAddress); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (Station != mAddress.Station) | ||||
|             easyLock.Wait(); | ||||
|  | ||||
|             ModbusAddress mAddress; | ||||
|             try | ||||
|             { | ||||
|                 return new OperResult<byte[]>("地址错误"); | ||||
|                 mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|             } | ||||
|             Init(mAddress); | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 return new OperResult<byte[]>(ex); | ||||
|             } | ||||
|             if (MulStation) | ||||
|             { | ||||
|                 Init(mAddress); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (Station != mAddress.Station) | ||||
|                 { | ||||
|                     return new OperResult<byte[]>("地址错误"); | ||||
|                 } | ||||
|                 Init(mAddress); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station]; | ||||
|             int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength; | ||||
|             switch (mAddress.ReadFunction) | ||||
|             { | ||||
|                 case 1: | ||||
|                     byte[] bytes0 = new byte[len]; | ||||
|                     ModbusServer01ByteBlock.Pos = mAddress.AddressStart; | ||||
|                     ModbusServer01ByteBlock.Read(bytes0); | ||||
|                     return OperResult.CreateSuccessResult(bytes0); | ||||
|                 case 2: | ||||
|                     byte[] bytes1 = new byte[len]; | ||||
|                     ModbusServer02ByteBlock.Pos = mAddress.AddressStart; | ||||
|                     ModbusServer02ByteBlock.Read(bytes1); | ||||
|                     return OperResult.CreateSuccessResult(bytes1); | ||||
|                 case 3: | ||||
|  | ||||
|                     byte[] bytes3 = new byte[len]; | ||||
|                     ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                     ModbusServer03ByteBlock.Read(bytes3); | ||||
|                     return OperResult.CreateSuccessResult(bytes3); | ||||
|                 case 4: | ||||
|                     byte[] bytes4 = new byte[len]; | ||||
|                     ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                     ModbusServer04ByteBlock.Read(bytes4); | ||||
|                     return OperResult.CreateSuccessResult(bytes4); | ||||
|             } | ||||
|             return new OperResult<byte[]>("功能码错误"); | ||||
|         } | ||||
|  | ||||
|         var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station]; | ||||
|         int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength; | ||||
|         switch (mAddress.ReadFunction) | ||||
|         finally | ||||
|         { | ||||
|             case 1: | ||||
|                 byte[] bytes0 = new byte[len]; | ||||
|                 ModbusServer01ByteBlock.Pos = mAddress.AddressStart; | ||||
|                 ModbusServer01ByteBlock.Read(bytes0); | ||||
|                 return OperResult.CreateSuccessResult(bytes0); | ||||
|             case 2: | ||||
|                 byte[] bytes1 = new byte[len]; | ||||
|                 ModbusServer02ByteBlock.Pos = mAddress.AddressStart; | ||||
|                 ModbusServer02ByteBlock.Read(bytes1); | ||||
|                 return OperResult.CreateSuccessResult(bytes1); | ||||
|             case 3: | ||||
|  | ||||
|                 byte[] bytes3 = new byte[len]; | ||||
|                 ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                 ModbusServer03ByteBlock.Read(bytes3); | ||||
|                 return OperResult.CreateSuccessResult(bytes3); | ||||
|             case 4: | ||||
|                 byte[] bytes4 = new byte[len]; | ||||
|                 ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                 ModbusServer04ByteBlock.Read(bytes4); | ||||
|                 return OperResult.CreateSuccessResult(bytes4); | ||||
|             easyLock.Release(); | ||||
|         } | ||||
|         return new OperResult<byte[]>("功能码错误"); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
| @@ -193,84 +206,104 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase | ||||
|     /// <inheritdoc/> | ||||
|     public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         ModbusAddress mAddress; | ||||
|         try | ||||
|         { | ||||
|             mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult(ex); | ||||
|         } | ||||
|         if (MulStation) | ||||
|         { | ||||
|             Init(mAddress); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (Station != mAddress.Station) | ||||
|             easyLock.Wait(); | ||||
|             ModbusAddress mAddress; | ||||
|             try | ||||
|             { | ||||
|                 return new OperResult("地址错误"); | ||||
|                 mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|             } | ||||
|             Init(mAddress); | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 return new OperResult(ex); | ||||
|             } | ||||
|             if (MulStation) | ||||
|             { | ||||
|                 Init(mAddress); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (Station != mAddress.Station) | ||||
|                 { | ||||
|                     return new OperResult("地址错误"); | ||||
|                 } | ||||
|                 Init(mAddress); | ||||
|             } | ||||
|             var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station]; | ||||
|             switch (mAddress.ReadFunction) | ||||
|             { | ||||
|                 case 3: | ||||
|                     ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                     ModbusServer03ByteBlock.Write(value); | ||||
|                     return OperResult.CreateSuccessResult(); | ||||
|                 case 4: | ||||
|                     ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                     ModbusServer04ByteBlock.Write(value); | ||||
|                     return OperResult.CreateSuccessResult(); | ||||
|             } | ||||
|             return new OperResult("功能码错误"); | ||||
|  | ||||
|         } | ||||
|         var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station]; | ||||
|         switch (mAddress.ReadFunction) | ||||
|         finally | ||||
|         { | ||||
|             case 3: | ||||
|                 ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                 ModbusServer03ByteBlock.Write(value); | ||||
|                 return OperResult.CreateSuccessResult(); | ||||
|             case 4: | ||||
|                 ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength; | ||||
|                 ModbusServer04ByteBlock.Write(value); | ||||
|                 return OperResult.CreateSuccessResult(); | ||||
|  | ||||
|             easyLock.Release(); | ||||
|         } | ||||
|         return new OperResult("功能码错误"); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         ModbusAddress mAddress; | ||||
|         try | ||||
|         { | ||||
|             mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return (new OperResult(ex)); | ||||
|         } | ||||
|         if (MulStation) | ||||
|         { | ||||
|             Init(mAddress); | ||||
|  | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (Station != mAddress.Station) | ||||
|             easyLock.Wait(); | ||||
|             ModbusAddress mAddress; | ||||
|             try | ||||
|             { | ||||
|                 return (new OperResult("地址错误")); | ||||
|                 mAddress = ModbusAddress.ParseFrom(address, Station); | ||||
|             } | ||||
|             Init(mAddress); | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 return (new OperResult(ex)); | ||||
|             } | ||||
|             if (MulStation) | ||||
|             { | ||||
|                 Init(mAddress); | ||||
|  | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (Station != mAddress.Station) | ||||
|                 { | ||||
|                     return (new OperResult("地址错误")); | ||||
|                 } | ||||
|                 Init(mAddress); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station]; | ||||
|             var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station]; | ||||
|             switch (mAddress.ReadFunction) | ||||
|             { | ||||
|                 case 1: | ||||
|                     ModbusServer01ByteBlock.Pos = mAddress.AddressStart; | ||||
|                     ModbusServer01ByteBlock.Write(value.BoolArrayToByte()); | ||||
|                     return (OperResult.CreateSuccessResult()); | ||||
|                 case 2: | ||||
|                     ModbusServer02ByteBlock.Pos = mAddress.AddressStart; | ||||
|                     ModbusServer02ByteBlock.Write(value.BoolArrayToByte()); | ||||
|                     return (OperResult.CreateSuccessResult()); | ||||
|             } | ||||
|             return new OperResult("功能码错误"); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station]; | ||||
|         var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station]; | ||||
|         switch (mAddress.ReadFunction) | ||||
|         finally | ||||
|         { | ||||
|             case 1: | ||||
|                 ModbusServer01ByteBlock.Pos = mAddress.AddressStart; | ||||
|                 ModbusServer01ByteBlock.Write(value.BoolArrayToByte()); | ||||
|                 return (OperResult.CreateSuccessResult()); | ||||
|             case 2: | ||||
|                 ModbusServer02ByteBlock.Pos = mAddress.AddressStart; | ||||
|                 ModbusServer02ByteBlock.Write(value.BoolArrayToByte()); | ||||
|                 return (OperResult.CreateSuccessResult()); | ||||
|  | ||||
|             easyLock.Release(); | ||||
|         } | ||||
|         return new OperResult("功能码错误"); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
| @@ -429,13 +462,9 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase | ||||
|  | ||||
|     private void Init(ModbusAddress mAddress) | ||||
|     { | ||||
|         if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128))) | ||||
|             ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128); | ||||
|         if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128))) | ||||
|             ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128); | ||||
|         if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128))) | ||||
|             ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128); | ||||
|         if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128))) | ||||
|             ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128); | ||||
|         ModbusServer01ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128)); | ||||
|         ModbusServer02ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128)); | ||||
|         ModbusServer03ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128)); | ||||
|         ModbusServer04ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -57,7 +57,7 @@ public class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesTcpDataHandleAda | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<byte[]>(ex.Message); | ||||
|             return new OperResult<byte[]>(ex); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -176,7 +176,7 @@ internal class OpcServer : IDisposable | ||||
|                 { | ||||
|                     status = (OPCSERVERSTATUS)o; | ||||
|                     serverStatus = new(); | ||||
|                     serverStatus.Version = status.wMajorVersion.ToString() + "." + status.wMinorVersion.ToString() + "." + status.wBuildNumber.ToString(); | ||||
|                     serverStatus.Version = $"{status.wMajorVersion.ToString()}.{status.wMinorVersion.ToString()}.{status.wBuildNumber.ToString()}"; | ||||
|                     serverStatus.ServerState = status.dwServerState; | ||||
|                     serverStatus.StartTime = Comn.Convert.FileTimeToDateTime(status.ftStartTime); | ||||
|                     serverStatus.CurrentTime = Comn.Convert.FileTimeToDateTime(status.ftCurrentTime); | ||||
|   | ||||
| @@ -17,22 +17,23 @@ using Opc.Ua.Client; | ||||
| using Opc.Ua.Client.ComplexTypes; | ||||
| using Opc.Ua.Configuration; | ||||
|  | ||||
|  | ||||
| //修改自https://github.com/dathlin/OpcUaHelper 与OPC基金会net库 | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Adapter.OPCUA; | ||||
|  | ||||
| /// <summary> | ||||
| /// 订阅委托 | ||||
| /// </summary> | ||||
| /// <param name="value"></param> | ||||
| public delegate void DataChangedEventHandler((VariableNode variableNode, DataValue dataValue, JToken jToken) value); | ||||
|  | ||||
| /// <summary> | ||||
| /// OPCUAClient | ||||
| /// </summary> | ||||
| public class OPCUAClient : IDisposable | ||||
| { | ||||
|  | ||||
|     #region 属性,变量等 | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 当前配置 | ||||
|     /// </summary> | ||||
| @@ -48,30 +49,35 @@ public class OPCUAClient : IDisposable | ||||
|     /// </summary> | ||||
|     public List<string> Variables = new(); | ||||
|  | ||||
|     private readonly Action<byte, object, string, Exception> _logAction; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 当前的变量名称/OPC变量节点 | ||||
|     /// </summary> | ||||
|     private readonly Dictionary<string, VariableNode> _variableDicts = new(); | ||||
|  | ||||
|     private readonly object checkLock = new(); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 当前的订阅组,组名称/组 | ||||
|     /// </summary> | ||||
|     private readonly Dictionary<string, Subscription> dic_subscriptions = new(); | ||||
|  | ||||
|     private readonly ApplicationInstance m_application = new(); | ||||
|  | ||||
|     private readonly ApplicationConfiguration m_configuration; | ||||
|     private SessionReconnectHandler m_reConnectHandler; | ||||
|     private EventHandler m_ReconnectComplete; | ||||
|     private EventHandler m_ReconnectStarting; | ||||
|     private EventHandler<KeepAliveEventArgs> m_KeepAliveComplete; | ||||
|     private EventHandler<bool> m_ConnectComplete; | ||||
|     private EventHandler<OpcUaStatusEventArgs> m_OpcStatusChange; | ||||
|  | ||||
|     private ISession m_session; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 默认的构造函数,实例化一个新的OPC UA类 | ||||
|     /// </summary> | ||||
|     public OPCUAClient(Action<byte, object, string, Exception> log) | ||||
|     public OPCUAClient() | ||||
|     { | ||||
|         _logAction = log; | ||||
|         var certificateValidator = new CertificateValidator(); | ||||
|         certificateValidator.CertificateValidation += CertificateValidation; | ||||
|  | ||||
| @@ -90,7 +96,6 @@ public class OPCUAClient : IDisposable | ||||
|                 MaxMessageQueueSize = 1000000, | ||||
|                 MaxNotificationQueueSize = 1000000, | ||||
|                 MaxPublishRequestCount = 10000000, | ||||
|  | ||||
|             }, | ||||
|  | ||||
|             SecurityConfiguration = new SecurityConfiguration | ||||
| @@ -133,8 +138,6 @@ public class OPCUAClient : IDisposable | ||||
|                     StoreType = CertificateStoreType.Directory, | ||||
|                     StorePath = AppContext.BaseDirectory + @"OPCUAClientCertificate\pki\trustedUser", | ||||
|                 } | ||||
|  | ||||
|  | ||||
|             }, | ||||
|  | ||||
|             TransportQuotas = new TransportQuotas | ||||
| @@ -160,8 +163,6 @@ public class OPCUAClient : IDisposable | ||||
|  | ||||
|         m_configuration.Validate(ApplicationType.Client); | ||||
|         m_application.ApplicationConfiguration = m_configuration; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -188,6 +189,52 @@ public class OPCUAClient : IDisposable | ||||
|     /// SessionReconnectHandler | ||||
|     /// </summary> | ||||
|     public SessionReconnectHandler ReConnectHandler => m_reConnectHandler; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Raised when a good keep alive from the server arrives. | ||||
|     /// </summary> | ||||
|     public event EventHandler<KeepAliveEventArgs> KeepAliveComplete | ||||
|     { | ||||
|         add { m_KeepAliveComplete += value; } | ||||
|         remove { m_KeepAliveComplete -= value; } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Raised when a reconnect operation starts. | ||||
|     /// </summary> | ||||
|     public event EventHandler ReconnectStarting | ||||
|     { | ||||
|         add { m_ReconnectStarting += value; } | ||||
|         remove { m_ReconnectStarting -= value; } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Raised when a reconnect operation completes. | ||||
|     /// </summary> | ||||
|     public event EventHandler ReconnectComplete | ||||
|     { | ||||
|         add { m_ReconnectComplete += value; } | ||||
|         remove { m_ReconnectComplete -= value; } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Raised after successfully connecting to or disconnecing from a server. | ||||
|     /// </summary> | ||||
|     public event EventHandler<bool> ConnectComplete | ||||
|     { | ||||
|         add { m_ConnectComplete += value; } | ||||
|         remove { m_ConnectComplete -= value; } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Raised after the client status change | ||||
|     /// </summary> | ||||
|     public event EventHandler<OpcUaStatusEventArgs> OpcStatusChange | ||||
|     { | ||||
|         add { m_OpcStatusChange += value; } | ||||
|         remove { m_OpcStatusChange -= value; } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 当前活动会话。 | ||||
|     /// </summary> | ||||
| @@ -231,7 +278,7 @@ public class OPCUAClient : IDisposable | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 _logAction?.Invoke(3, this, $"初始化{items[i]}变量订阅失败", ex); | ||||
|                 UpdateStatus(3, DateTime.Now, $"初始化{items[i]}变量订阅失败,错误原因:{ex}"); | ||||
|             } | ||||
|         } | ||||
|         m_subscription.AddItems(monitoredItems); | ||||
| @@ -247,9 +294,9 @@ public class OPCUAClient : IDisposable | ||||
|         var isError = m_subscription.MonitoredItems.Any(a => a.Status.Error != null && StatusCode.IsBad(a.Status.Error.StatusCode)); | ||||
|         if (isError) | ||||
|         { | ||||
|             _logAction?.Invoke(3, this, $"创建以下变量订阅失败:{Environment.NewLine}{m_subscription.MonitoredItems.Where( | ||||
|             UpdateStatus(3, DateTime.Now, $"创建以下变量订阅失败:{Environment.NewLine}{m_subscription.MonitoredItems.Where( | ||||
|                 a => a.Status.Error != null && StatusCode.IsBad(a.Status.Error.StatusCode)) | ||||
|                 .Select(a => a.StartNodeId.ToString() + ":" + a.Status.Error.ToString()).ToJsonString()}", null); | ||||
|                 .Select(a => $"{a.StartNodeId.ToString()}:{a.Status.Error.ToString()}").ToJsonString()}"); | ||||
|         } | ||||
|  | ||||
|         lock (dic_subscriptions) | ||||
| @@ -281,7 +328,6 @@ public class OPCUAClient : IDisposable | ||||
|                 item.Value.Delete(true); | ||||
|                 m_session.RemoveSubscription(item.Value); | ||||
|                 try { item.Value.Dispose(); } catch { } | ||||
|  | ||||
|             } | ||||
|             dic_subscriptions.Clear(); | ||||
|         } | ||||
| @@ -304,39 +350,40 @@ public class OPCUAClient : IDisposable | ||||
|                 dic_subscriptions.RemoveWhere(a => a.Key == subscriptionName); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     private void Callback(MonitoredItem monitoreditem, MonitoredItemNotificationEventArgs monitoredItemNotificationEventArgs) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             var variableNode = ReadNode(monitoreditem.StartNodeId.ToString(), false); | ||||
|             foreach (var value in monitoreditem.DequeueValues()) | ||||
|             if (m_session != null) | ||||
|             { | ||||
|                 if (value.Value != null) | ||||
|                 var variableNode = ReadNode(monitoreditem.StartNodeId.ToString(), false); | ||||
|                 foreach (var value in monitoreditem.DequeueValues()) | ||||
|                 { | ||||
|                     var data = JsonUtils.Encode(m_session.MessageContext, TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable), value.Value); | ||||
|                     if (data == null && value.Value != null) | ||||
|                     if (value.Value != null) | ||||
|                     { | ||||
|                         _logAction?.Invoke(3, this, $"{monitoreditem.StartNodeId}转换出错,原始值String为{value.Value}", null); | ||||
|                         var data1 = JsonUtils.Encode(m_session.MessageContext, TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable), value.Value); | ||||
|                         var data = JsonUtils.Encode(m_session.MessageContext, TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable), value.Value); | ||||
|                         if (data == null && value.Value != null) | ||||
|                         { | ||||
|                             UpdateStatus(3, DateTime.Now, $"{monitoreditem.StartNodeId}转换出错,原始值String为{value.Value}"); | ||||
|                             var data1 = JsonUtils.Encode(m_session.MessageContext, TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable), value.Value); | ||||
|                         } | ||||
|                         DataChangedHandler?.Invoke((variableNode, value, data)); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         var data = JValue.CreateNull(); | ||||
|                         DataChangedHandler?.Invoke((variableNode, value, data)); | ||||
|                     } | ||||
|                     DataChangedHandler?.Invoke((variableNode, value, data)); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     var data = JValue.CreateNull(); | ||||
|                     DataChangedHandler?.Invoke((variableNode, value, data)); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logAction?.Invoke(3, this, $"{monitoreditem.StartNodeId}订阅处理错误", ex); | ||||
|             UpdateStatus(3, DateTime.Now, $"{monitoreditem.StartNodeId}订阅处理错误,错误原因:" + ex); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     #endregion | ||||
| @@ -462,8 +509,8 @@ public class OPCUAClient : IDisposable | ||||
|  | ||||
|     #endregion | ||||
|  | ||||
|  | ||||
|     #region 连接 | ||||
|  | ||||
|     private ComplexTypeSystem typeSystem; | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -472,7 +519,6 @@ public class OPCUAClient : IDisposable | ||||
|     public async Task ConnectAsync() | ||||
|     { | ||||
|         await ConnectAsync(OPCNode.OPCUrl); | ||||
|         _logAction?.Invoke(1, this, $"连接成功", null); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -484,10 +530,10 @@ public class OPCUAClient : IDisposable | ||||
|         // disconnect any existing session. | ||||
|         if (m_session != null) | ||||
|         { | ||||
|             _logAction?.Invoke(1, this, $"主动断开连接", null); | ||||
|             m_session = null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Creates a new session. | ||||
|     /// </summary> | ||||
| @@ -516,20 +562,24 @@ public class OPCUAClient : IDisposable | ||||
|         //创建本地证书 | ||||
|         await m_application.CheckApplicationInstanceCertificate(true, 0, 1200); | ||||
|         m_session = await Opc.Ua.Client.Session.Create( | ||||
|      m_configuration, | ||||
|     endpoint, | ||||
|     false, | ||||
|     OPCNode.CheckDomain, | ||||
|     (string.IsNullOrEmpty(OPCUAName)) ? m_configuration.ApplicationName : OPCUAName, | ||||
|     60000, | ||||
|     userIdentity, | ||||
|     Array.Empty<string>()); | ||||
|  | ||||
|         m_configuration, | ||||
|         endpoint, | ||||
|         false, | ||||
|         OPCNode.CheckDomain, | ||||
|         (string.IsNullOrEmpty(OPCUAName)) ? m_configuration.ApplicationName : OPCUAName, | ||||
|         60000, | ||||
|         userIdentity, | ||||
|         Array.Empty<string>()); | ||||
|         typeSystem = new ComplexTypeSystem(m_session); | ||||
|  | ||||
|         m_session.KeepAliveInterval = OPCNode.KeepAliveInterval == 0 ? 60000 : OPCNode.KeepAliveInterval; | ||||
|         m_session.KeepAlive += new KeepAliveEventHandler(Session_KeepAlive); | ||||
|  | ||||
|         // raise an event. | ||||
|         DoConnectComplete(true); | ||||
|  | ||||
|         UpdateStatus(2, DateTime.UtcNow, "Connected"); | ||||
|  | ||||
|         //如果是订阅模式,连接时添加订阅组 | ||||
|         if (OPCNode.ActiveSubscribe) | ||||
|             await AddSubscriptionAsync(Guid.NewGuid().ToString(), Variables.ToArray(), OPCNode.LoadType); | ||||
| @@ -538,6 +588,9 @@ public class OPCUAClient : IDisposable | ||||
|  | ||||
|     private void PrivateDisconnect() | ||||
|     { | ||||
|         bool state = m_session?.Connected == true; | ||||
|  | ||||
|  | ||||
|         if (m_reConnectHandler != null) | ||||
|         { | ||||
|             try { m_reConnectHandler.Dispose(); } catch { } | ||||
| @@ -549,8 +602,14 @@ public class OPCUAClient : IDisposable | ||||
|             m_session.Close(10000); | ||||
|         } | ||||
|  | ||||
|         if (state) | ||||
|         { | ||||
|             UpdateStatus(2, DateTime.UtcNow, "Disconnected"); | ||||
|             DoConnectComplete(false); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     #endregion | ||||
|  | ||||
|     #region 读取/写入 | ||||
| @@ -593,7 +652,6 @@ public class OPCUAClient : IDisposable | ||||
|                 valuesToWrite.Add(valueToWrite); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             var result = await m_session.WriteAsync( | ||||
|      requestHeader: null, | ||||
|      nodesToWrite: valuesToWrite, cancellationToken); | ||||
| @@ -601,7 +659,6 @@ public class OPCUAClient : IDisposable | ||||
|             ClientBase.ValidateResponse(result.Results, valuesToWrite); | ||||
|             ClientBase.ValidateDiagnosticInfos(result.DiagnosticInfos, valuesToWrite); | ||||
|  | ||||
|  | ||||
|             var keys = writeInfoLists.Keys.ToList(); | ||||
|             for (int i = 0; i < keys.Count; i++) | ||||
|             { | ||||
| @@ -624,7 +681,6 @@ public class OPCUAClient : IDisposable | ||||
|             } | ||||
|             return results; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -706,7 +762,6 @@ public class OPCUAClient : IDisposable | ||||
|         return node; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 从服务器读取节点 | ||||
|     /// </summary> | ||||
| @@ -729,18 +784,14 @@ public class OPCUAClient : IDisposable | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logAction?.Invoke(3, this, $"获取服务器节点信息失败{nodes.Item2[i]}", null); | ||||
|                 UpdateStatus(3, DateTime.Now, $"获取服务器节点信息失败{nodes.Item2[i]}"); | ||||
|             } | ||||
|         } | ||||
|         return nodes.Item1.ToList(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     #endregion | ||||
|  | ||||
|  | ||||
|  | ||||
|     #region 特性 | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -805,7 +856,6 @@ public class OPCUAClient : IDisposable | ||||
|                 ResultMask = (uint)BrowseResultMask.All | ||||
|             }; | ||||
|             nodesToBrowse.Add(nodeToBrowse); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return await ReadNoteAttributeAsync(nodesToBrowse, nodesToRead, cancellationToken); | ||||
| @@ -968,11 +1018,9 @@ public class OPCUAClient : IDisposable | ||||
|  | ||||
|         return nodeAttribute.ToArray(); | ||||
|     } | ||||
|  | ||||
|     #endregion | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public void Dispose() | ||||
|     { | ||||
| @@ -991,7 +1039,6 @@ public class OPCUAClient : IDisposable | ||||
|             throw new Exception(string.Format("验证证书失败,错误代码:{0}: {1}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo)); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     private async Task<Dictionary<string, List<OPCNodeAttribute>>> ReadNoteAttributeAsync(BrowseDescriptionCollection nodesToBrowse, ReadValueIdCollection nodesToRead, CancellationToken cancellationToken) | ||||
|     { | ||||
|         int startOfProperties = nodesToRead.Count; | ||||
| @@ -1068,7 +1115,6 @@ public class OPCUAClient : IDisposable | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|             if (nodeAttributes.ContainsKey(nodeToRead.NodeId.ToString())) | ||||
|             { | ||||
|                 nodeAttributes[nodeToRead.NodeId.ToString()].Add(item); | ||||
| @@ -1086,21 +1132,47 @@ public class OPCUAClient : IDisposable | ||||
|     /// </summary> | ||||
|     private void Server_ReconnectComplete(object sender, EventArgs e) | ||||
|     { | ||||
|         if (!Object.ReferenceEquals(sender, m_reConnectHandler)) | ||||
|         try | ||||
|         { | ||||
|             return; | ||||
|             if (!Object.ReferenceEquals(sender, m_reConnectHandler)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             m_session = m_reConnectHandler.Session; | ||||
|             m_reConnectHandler.Dispose(); | ||||
|             m_reConnectHandler = null; | ||||
|  | ||||
|             // raise any additional notifications. | ||||
|             m_ReconnectComplete?.Invoke(this, e); | ||||
|         } | ||||
|         catch (Exception) | ||||
|         { | ||||
|             throw; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         m_session = m_reConnectHandler.Session; | ||||
|         m_reConnectHandler = null; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Report the client status | ||||
|     /// </summary> | ||||
|     /// <param name="logLevel">Whether the status represents an error. </param> | ||||
|     /// <param name="time">The time associated with the status.</param> | ||||
|     /// <param name="status">The status message.</param> | ||||
|     /// <param name="args">Arguments used to format the status message.</param> | ||||
|     private void UpdateStatus(int logLevel, DateTime time, string status, params object[] args) | ||||
|     { | ||||
|         m_OpcStatusChange?.Invoke(this, new OpcUaStatusEventArgs() | ||||
|         { | ||||
|             LogLevel = logLevel, | ||||
|             Time = time.ToLocalTime(), | ||||
|             Text = String.Format(status, args), | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     private void Session_KeepAlive(ISession session, KeepAliveEventArgs e) | ||||
|     { | ||||
|         lock (checkLock) | ||||
|         { | ||||
|  | ||||
|             if (!Object.ReferenceEquals(session, m_session)) | ||||
|             { | ||||
|                 return; | ||||
| @@ -1108,22 +1180,39 @@ public class OPCUAClient : IDisposable | ||||
|  | ||||
|             if (ServiceResult.IsBad(e.Status)) | ||||
|             { | ||||
|                 _logAction?.Invoke(3, this, $"心跳检测错误:{e.Status}", null); | ||||
|                 if (m_session.KeepAliveInterval <= 0) | ||||
|                 { | ||||
|                     UpdateStatus(3, e.CurrentTime, "Communication Error ({0})", e.Status); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 UpdateStatus(3, e.CurrentTime, "Reconnecting in {0}s", m_session.KeepAliveInterval / 1000); | ||||
|  | ||||
|                 if (m_reConnectHandler == null) | ||||
|                 { | ||||
|                     m_ReconnectStarting?.Invoke(this, e); | ||||
|  | ||||
|                     m_reConnectHandler = new SessionReconnectHandler(); | ||||
|                     m_reConnectHandler.BeginReconnect(m_session, m_session.KeepAliveInterval, Server_ReconnectComplete); | ||||
|                 } | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // update status. | ||||
|             UpdateStatus(0, e.CurrentTime, "Session_KeepAlive Connected [{0}]", session.Endpoint.EndpointUrl); | ||||
|  | ||||
|             // raise any additional notifications. | ||||
|             m_KeepAliveComplete?.Invoke(this, e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Raises the connect complete event on the main GUI thread. | ||||
|     /// </summary> | ||||
|     private void DoConnectComplete(bool state) | ||||
|     { | ||||
|         m_ConnectComplete?.Invoke(this, state); | ||||
|     } | ||||
|  | ||||
|     #endregion | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| #region copyright | ||||
| #region copyright | ||||
| //------------------------------------------------------------------------------ | ||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||
| @@ -13,6 +13,33 @@ | ||||
| using Opc.Ua; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Adapter.OPCUA; | ||||
|  | ||||
| /// <summary> | ||||
| /// OPC UA的状态更新消息 | ||||
| /// </summary> | ||||
| public class OpcUaStatusEventArgs | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 日志等级,<br></br> | ||||
|     /// 更为详细的步骤型日志输出 Trace = 0,<br></br> | ||||
|     /// 调试信息日志Debug = 1,<br></br> | ||||
|     /// 消息类日志输出 Info = 2,<br></br> | ||||
|     /// 警告类日志输出 Warning = 3,<br></br> | ||||
|     /// 错误类日志输出 Error = 4,<br></br> | ||||
|     /// 不可控中断类日输出Critical = 5, | ||||
|     /// </summary> | ||||
|     public int LogLevel { get; set; } | ||||
|     /// <summary> | ||||
|     /// 时间 | ||||
|     /// </summary> | ||||
|     public DateTime Time { get; set; } | ||||
|     /// <summary> | ||||
|     /// 文本 | ||||
|     /// </summary> | ||||
|     public string Text { get; set; } | ||||
|  | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// 读取属性过程中用于描述的 | ||||
| /// </summary> | ||||
| @@ -22,6 +49,7 @@ public class OPCNodeAttribute | ||||
|     /// 属性的名称 | ||||
|     /// </summary> | ||||
|     public string Name { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 操作结果状态描述 | ||||
|     /// </summary> | ||||
| @@ -31,10 +59,9 @@ public class OPCNodeAttribute | ||||
|     /// 属性的类型描述 | ||||
|     /// </summary> | ||||
|     public string Type { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 属性的值,如果读取错误,返回文本描述 | ||||
|     /// </summary> | ||||
|     public object Value { get; set; } | ||||
|  | ||||
| } | ||||
|  | ||||
| } | ||||
| @@ -11,5 +11,4 @@ | ||||
| 		<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.56" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
| </Project> | ||||
|   | ||||
| @@ -250,44 +250,44 @@ public class SiemensAddress : DeviceAddressBase | ||||
|     { | ||||
|         if (DataCode == (byte)S7Area.TM) | ||||
|         { | ||||
|             return "T" + Address.ToString() + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|             return $"T{Address.ToString()}{(IsWString ? ";W=true;" : ";W=false;")}"; | ||||
|         } | ||||
|         if (DataCode == (byte)S7Area.CT) | ||||
|         { | ||||
|             return "C" + Address.ToString() + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|             return $"C{Address.ToString()}{(IsWString ? ";W=true;" : ";W=false;")}"; | ||||
|         } | ||||
|  | ||||
|         if (DataCode == (byte)S7Area.AI) | ||||
|         { | ||||
|             return "AI" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|             return $"AI{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}"; | ||||
|         } | ||||
|  | ||||
|         if (DataCode == (byte)S7Area.AQ) | ||||
|         { | ||||
|             return "AQ" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|             return $"AQ{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}"; | ||||
|         } | ||||
|  | ||||
|         if (DataCode == (byte)S7Area.PE) | ||||
|         { | ||||
|             return "I" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|             return $"I{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}"; | ||||
|         } | ||||
|  | ||||
|         if (DataCode == (byte)S7Area.PA) | ||||
|         { | ||||
|             return "Q" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|             return $"Q{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}"; | ||||
|         } | ||||
|  | ||||
|         if (DataCode == (byte)S7Area.MK) | ||||
|         { | ||||
|             return "M" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|             return $"M{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}"; | ||||
|         } | ||||
|  | ||||
|         return DataCode == (byte)S7Area.DB ? "DB" + DbBlock.ToString() + "." + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;") : Address.ToString() + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|         return DataCode == (byte)S7Area.DB ? $"DB{DbBlock.ToString()}.{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}" : Address.ToString() + (IsWString ? ";W=true;" : ";W=false;"); | ||||
|     } | ||||
|  | ||||
|     private static string GetStringAddress(int addressStart) | ||||
|     { | ||||
|         return addressStart % 8 == 0 ? (addressStart / 8).ToString() : string.Format("{0}.{1}", addressStart / 8, addressStart % 8); | ||||
|         return addressStart % 8 == 0 ? (addressStart / 8).ToString() : $"{addressStart / 8}.{addressStart % 8}"; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -36,11 +36,42 @@ internal partial class SiemensHelper | ||||
|     //    return OperResult.CreateSuccessResult<byte[]>(numArray); | ||||
|     //} | ||||
|  | ||||
|     internal static OperResult<byte[]> AnalysisReadByte(byte[] sends, byte[] content) | ||||
|     internal static OperResult<byte[], FilterResult> AnalysisReadByte(byte[] sends, byte[] content) | ||||
|     { | ||||
|         int length = 0; | ||||
|         int itemLen = (sends.Length - 19) / 12; | ||||
|  | ||||
|         //添加错误代码校验 | ||||
|         if (content[17] + content[18] > 0) | ||||
|         { | ||||
|             return new($"PLC返回错误,错误类型{content[17].ToString("X2")}错误代码:{content[18].ToString("X2")}") | ||||
|             { | ||||
|                 Content2 = FilterResult.Success | ||||
|             }; | ||||
|         } | ||||
|         if (content.Length < 21) | ||||
|         { | ||||
|             return new($"长度不足") | ||||
|             { | ||||
|                 Content2 = FilterResult.Cache | ||||
|             }; | ||||
|         } | ||||
|         if (content.Length < 25 + content[20]) | ||||
|         { | ||||
|             return new($"长度不足") | ||||
|             { | ||||
|                 Content2 = FilterResult.Cache | ||||
|             }; | ||||
|         } | ||||
|         //添加返回代码校验 | ||||
|         if (content[21] != 0xff) | ||||
|         { | ||||
|             return new($"PLC返回错误,返回代码{content[21].ToString("X2")}") | ||||
|             { | ||||
|                 Content2 = FilterResult.Success | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         for (int index = 0; index < itemLen; index++) | ||||
|         { | ||||
|             if (sends[22 + (index * 12)] >= (byte)S7WordLength.Word) | ||||
| @@ -53,9 +84,9 @@ internal partial class SiemensHelper | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (content.Length < 21 || content[20] != itemLen) | ||||
|         if (content[20] != itemLen) | ||||
|         { | ||||
|             return new OperResult<byte[]>("数据块长度校验失败"); | ||||
|             return new("数据块长度校验失败"); | ||||
|         } | ||||
|  | ||||
|         byte[] dataArray = new byte[length]; | ||||
| @@ -105,29 +136,39 @@ internal partial class SiemensHelper | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     return new OperResult<byte[]>((int)content[index2] + GetCpuError(content[index2])); | ||||
|                     return new((int)content[index2] + GetCpuError(content[index2])) | ||||
|                     { | ||||
|                         Content2 = FilterResult.Success | ||||
|                     }; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return OperResult.CreateSuccessResult(dataArray); | ||||
|         return OperResult.CreateSuccessResult(dataArray, FilterResult.Success); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     internal static OperResult<byte[]> AnalysisWrite(byte[] content) | ||||
|     internal static OperResult<byte[], FilterResult> AnalysisWrite(byte[] content) | ||||
|     { | ||||
|         if (content.Length < 22) | ||||
|         { | ||||
|             return new OperResult<byte[]>() { Message = "未知错误" }; | ||||
|             return new() | ||||
|             { | ||||
|                 Message = "长度不足", | ||||
|                 Content2 = FilterResult.Success | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         byte err = content[21]; | ||||
|         if (err != byte.MaxValue) | ||||
|         { | ||||
|             return new OperResult<byte[]>((int)content[21] + GetCpuError(content[21])); | ||||
|             return new($"错误代码:{(int)content[21]}描述:{GetCpuError(content[21])}") | ||||
|             { | ||||
|                 Content2 = FilterResult.Success | ||||
|             }; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return OperResult.CreateSuccessResult(content); | ||||
|             return OperResult.CreateSuccessResult(content, FilterResult.Success); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|   | ||||
| @@ -123,34 +123,7 @@ namespace ThingsGateway.Foundation.Adapter.Siemens | ||||
|         #region 设置 | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 远程TSAP,需重新连接 | ||||
|         /// </summary> | ||||
|         public int DestTSAP | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return | ||||
|                     _currentPlc == SiemensEnum.S200 || _currentPlc == SiemensEnum.S200Smart ? | ||||
|                     (ISO_CR[17] * 256) + ISO_CR[18] : | ||||
|                     (ISO_CR[20] * 256) + ISO_CR[21]; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 if (_currentPlc == SiemensEnum.S200 || _currentPlc == SiemensEnum.S200Smart) | ||||
|                 { | ||||
|                     ISO_CR[17] = BitConverter.GetBytes(value)[1]; | ||||
|                     ISO_CR[18] = BitConverter.GetBytes(value)[0]; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ISO_CR[20] = BitConverter.GetBytes(value)[1]; | ||||
|                     ISO_CR[21] = BitConverter.GetBytes(value)[0]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 本地TSAP,需重新连接 | ||||
|         /// 本地TSAP | ||||
|         /// </summary> | ||||
|         public int LocalTSAP | ||||
|         { | ||||
|   | ||||
| @@ -35,10 +35,10 @@ public class SiemensS7PLCDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapte | ||||
|     /// <inheritdoc/> | ||||
|     protected override FilterResult UnpackResponse(SiemensMessage request, byte[] send, byte[] body, byte[] response) | ||||
|     { | ||||
|         var result = new OperResult<byte[]>(); | ||||
|         var result = new OperResult<byte[], FilterResult>(); | ||||
|         if (response[2] * 256 + response[3] == 7) | ||||
|         { | ||||
|             result = new OperResult<byte[]>() { Content = response }; | ||||
|             result = new() { Content = response, Content2 = FilterResult.Success }; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| @@ -56,6 +56,6 @@ public class SiemensS7PLCDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapte | ||||
|         request.ErrorCode = result.ErrorCode; | ||||
|         request.Message = result.Message; | ||||
|         request.Content = result.Content; | ||||
|         return FilterResult.Success; | ||||
|         return result.Content2; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,15 @@ | ||||
| 0x00       Reserved 未定义,预留 | ||||
|  | ||||
| 0x01       Hardware error   硬件错误 | ||||
|  | ||||
| 0x03       Accessing the object not allowed 对象不允许访问 | ||||
|  | ||||
| 0x05       Invalid address     无效地址,所需的地址超出此PLC的极限 | ||||
|  | ||||
| 0x06       Data type not supported     数据类型不支持 | ||||
|  | ||||
| 0x07       Data type inconsistent 日期类型不一致 | ||||
|  | ||||
| 0x0a       Object does not exist    对象不存在 | ||||
|  | ||||
| 0xff         Success  成功 | ||||
| @@ -0,0 +1,825 @@ | ||||
| 附录一:错误码具体含义 | ||||
|  | ||||
| 0x0000 | ||||
|  | ||||
| 没有错误 | ||||
|  | ||||
| 0x0110 | ||||
|  | ||||
| 块号无效 | ||||
|  | ||||
| 0x0111 | ||||
|  | ||||
| 请求长度无效 | ||||
|  | ||||
| 0x0112 | ||||
|  | ||||
| 参数无效 | ||||
|  | ||||
| 0x0113 | ||||
|  | ||||
| 块类型无效 | ||||
|  | ||||
| 0x0114 | ||||
|  | ||||
| 找不到块 | ||||
|  | ||||
| 0x0115 | ||||
|  | ||||
| 块已存在 | ||||
|  | ||||
| 0x0116 | ||||
|  | ||||
| 块被写保护 | ||||
|  | ||||
| 0x0117 | ||||
|  | ||||
| 块/操作系统更新太大 | ||||
|  | ||||
| 0x0118 | ||||
|  | ||||
| 块号无效 | ||||
|  | ||||
| 0x0119 | ||||
|  | ||||
| 输入的密码不正确 | ||||
|  | ||||
| 0x011A | ||||
|  | ||||
| PG资源错误 | ||||
|  | ||||
| 0x011B | ||||
|  | ||||
| PLC资源错误 | ||||
|  | ||||
| 0x011C | ||||
|  | ||||
| 协议错误 | ||||
|  | ||||
| 0x011D | ||||
|  | ||||
| 块太多(与模块相关的限制) | ||||
|  | ||||
| 0x011E | ||||
|  | ||||
| 不再与数据库建立连接,或者S7DOS句柄无效 | ||||
|  | ||||
| 0x011F | ||||
|  | ||||
| 结果缓冲区太小 | ||||
|  | ||||
| 0x0120 | ||||
|  | ||||
| 块结束列表 | ||||
|  | ||||
| 0x0140 | ||||
|  | ||||
| 可用内存不足 | ||||
|  | ||||
| 0x0141 | ||||
|  | ||||
| 由于缺少资源,无法处理作业 | ||||
|  | ||||
| 0x8001 | ||||
|  | ||||
| 当块处于当前状态时,无法执行请求的服务 | ||||
|  | ||||
| 0x8003 | ||||
|  | ||||
| S7协议错误:传输块时发生错误 | ||||
|  | ||||
| 0x8100 | ||||
|  | ||||
| 应用程序,一般错误:远程模块未知的服务 | ||||
|  | ||||
| 0x8104 | ||||
|  | ||||
| 未在模块上实现此服务或报告了帧错误 | ||||
|  | ||||
| 0x8204 | ||||
|  | ||||
| 对象的类型规范不一致 | ||||
|  | ||||
| 0x8205 | ||||
|  | ||||
| 复制的块已存在且未链接 | ||||
|  | ||||
| 0x8301 | ||||
|  | ||||
| 模块上的内存空间或工作内存不足,或者指定的存储介质不可访问 | ||||
|  | ||||
| 0x8302 | ||||
|  | ||||
| 可用资源太少或处理器资源不可用 | ||||
|  | ||||
| 0x8304 | ||||
|  | ||||
| 无法进一步并行上传。存在资源瓶颈 | ||||
|  | ||||
| 0x8305 | ||||
|  | ||||
| 功能不可用 | ||||
|  | ||||
| 0x8306 | ||||
|  | ||||
| 工作内存不足(用于复制,链接,加载AWP) | ||||
|  | ||||
| 0x8307 | ||||
|  | ||||
| 保持性工作记忆不够(用于复制,链接,加载AWP) | ||||
|  | ||||
| 0x8401 | ||||
|  | ||||
| S7协议错误:无效的服务序列(例如,加载或上载块) | ||||
|  | ||||
| 0x8402 | ||||
|  | ||||
| 由于寻址对象的状态,服务无法执行 | ||||
|  | ||||
| 0x8404 | ||||
|  | ||||
| S7协议:无法执行该功能 | ||||
|  | ||||
| 0x8405 | ||||
|  | ||||
| 远程块处于DISABLE状态(CFB)。该功能无法执行 | ||||
|  | ||||
| 0x8500 | ||||
|  | ||||
| S7协议错误:帧错误 | ||||
|  | ||||
| 0x8503 | ||||
|  | ||||
| 来自模块的警报:服务过早取消 | ||||
|  | ||||
| 0x8701 | ||||
|  | ||||
| 寻址通信伙伴上的对象时出错(例如,区域长度错误) | ||||
|  | ||||
| 0x8702 | ||||
|  | ||||
| 模块不支持所请求的服务 | ||||
|  | ||||
| 0x8703 | ||||
|  | ||||
| 拒绝访问对象 | ||||
|  | ||||
| 0x8704 | ||||
|  | ||||
| 访问错误:对象已损坏 | ||||
|  | ||||
| 0xD001 | ||||
|  | ||||
| 协议错误:非法的作业号 | ||||
|  | ||||
| 0xD002 | ||||
|  | ||||
| 参数错误:非法的作业变体 | ||||
|  | ||||
| 0xD003 | ||||
|  | ||||
| 参数错误:模块不支持调试功能 | ||||
|  | ||||
| 0xD004 | ||||
|  | ||||
| 参数错误:作业状态非法 | ||||
|  | ||||
| 0xD005 | ||||
|  | ||||
| 参数错误:作业终止非法 | ||||
|  | ||||
| 0xD006 | ||||
|  | ||||
| 参数错误:非法链路断开ID | ||||
|  | ||||
| 0xD007 | ||||
|  | ||||
| 参数错误:缓冲区元素数量非法 | ||||
|  | ||||
| 0xD008 | ||||
|  | ||||
| 参数错误:扫描速率非法 | ||||
|  | ||||
| 0xD009 | ||||
|  | ||||
| 参数错误:执行次数非法 | ||||
|  | ||||
| 0xD00A | ||||
|  | ||||
| 参数错误:非法触发事件 | ||||
|  | ||||
| 0xD00B | ||||
|  | ||||
| 参数错误:非法触发条件 | ||||
|  | ||||
| 0xD011 | ||||
|  | ||||
| 调用环境路径中的参数错误:块不存在 | ||||
|  | ||||
| 0xD012 | ||||
|  | ||||
| 参数错误:块中的地址错误 | ||||
|  | ||||
| 0xD014 | ||||
|  | ||||
| 参数错误:正在删除/覆盖块 | ||||
|  | ||||
| 0xD015 | ||||
|  | ||||
| 参数错误:标签地址非法 | ||||
|  | ||||
| 0xD016 | ||||
|  | ||||
| 参数错误:由于用户程序错误,无法测试作业 | ||||
|  | ||||
| 0xD017 | ||||
|  | ||||
| 参数错误:非法触发号 | ||||
|  | ||||
| 0xD025 | ||||
|  | ||||
| 参数错误:路径无效 | ||||
|  | ||||
| 0xD026 | ||||
|  | ||||
| 参数错误:非法访问类型 | ||||
|  | ||||
| 0xD027 | ||||
|  | ||||
| 参数错误:不允许此数据块数 | ||||
|  | ||||
| 0xD031 | ||||
|  | ||||
| 内部协议错误 | ||||
|  | ||||
| 0xD032 | ||||
|  | ||||
| 参数错误:结果缓冲区长度错误 | ||||
|  | ||||
| 0xD033 | ||||
|  | ||||
| 协议错误:作业长度错误 | ||||
|  | ||||
| 0xD03F | ||||
|  | ||||
| 编码错误:参数部分出错(例如,保留字节不等于0) | ||||
|  | ||||
| 0xD041 | ||||
|  | ||||
| 数据错误:非法状态列表ID | ||||
|  | ||||
| 0xD042 | ||||
|  | ||||
| 数据错误:标签地址非法 | ||||
|  | ||||
| 0xD043 | ||||
|  | ||||
| 数据错误:找不到引用的作业,检查作业数据 | ||||
|  | ||||
| 0xD044 | ||||
|  | ||||
| 数据错误:标签值非法,检查作业数据 | ||||
|  | ||||
| 0xD045 | ||||
|  | ||||
| 数据错误:HOLD中不允许退出ODIS控制 | ||||
|  | ||||
| 0xD046 | ||||
|  | ||||
| 数据错误:运行时测量期间非法测量阶段 | ||||
|  | ||||
| 0xD047 | ||||
|  | ||||
| 数据错误:“读取作业列表”中的非法层次结构 | ||||
|  | ||||
| 0xD048 | ||||
|  | ||||
| 数据错误:“删除作业”中的非法删除ID | ||||
|  | ||||
| 0xD049 | ||||
|  | ||||
| “替换作业”中的替换ID无效 | ||||
|  | ||||
| 0xD04A | ||||
|  | ||||
| 执行'程序状态'时出错 | ||||
|  | ||||
| 0xD05F | ||||
|  | ||||
| 编码错误:数据部分出错(例如,保留字节不等于0,...) | ||||
|  | ||||
| 0xD061 | ||||
|  | ||||
| 资源错误:没有作业的内存空间 | ||||
|  | ||||
| 0xD062 | ||||
|  | ||||
| 资源错误:作业列表已满 | ||||
|  | ||||
| 0xD063 | ||||
|  | ||||
| 资源错误:触发事件占用 | ||||
|  | ||||
| 0xD064 | ||||
|  | ||||
| 资源错误:没有足够的内存空间用于一个结果缓冲区元素 | ||||
|  | ||||
| 0xD065 | ||||
|  | ||||
| 资源错误:没有足够的内存空间用于多个结果缓冲区元素 | ||||
|  | ||||
| 0xD066 | ||||
|  | ||||
| 资源错误:可用于运行时测量的计时器被另一个作业占用 | ||||
|  | ||||
| 0xD067 | ||||
|  | ||||
| 资源错误:“修改标记”作业过多(特别是多处理器操作) | ||||
|  | ||||
| 0xD081 | ||||
|  | ||||
| 当前模式下不允许使用的功能 | ||||
|  | ||||
| 0xD082 | ||||
|  | ||||
| 模式错误:无法退出HOLD模式 | ||||
|  | ||||
| 0xD0A1 | ||||
|  | ||||
| 当前保护级别不允许使用的功能 | ||||
|  | ||||
| 0xD0A2 | ||||
|  | ||||
| 目前无法运行,因为正在运行的函数会修改内存 | ||||
|  | ||||
| 0xD0A3 | ||||
|  | ||||
| I / O上活动的“修改标记”作业太多(特别是多处理器操作) | ||||
|  | ||||
| 0xD0A4 | ||||
|  | ||||
| '强制'已经建立 | ||||
|  | ||||
| 0xD0A5 | ||||
|  | ||||
| 找不到引用的作业 | ||||
|  | ||||
| 0xD0A6 | ||||
|  | ||||
| 无法禁用/启用作业 | ||||
|  | ||||
| 0xD0A7 | ||||
|  | ||||
| 无法删除作业,例如因为当前正在读取作业 | ||||
|  | ||||
| 0xD0A8 | ||||
|  | ||||
| 无法替换作业,例如因为当前正在读取或删除作业 | ||||
|  | ||||
| 0xD0A9 | ||||
|  | ||||
| 无法读取作业,例如因为当前正在删除作业 | ||||
|  | ||||
| 0xD0AA | ||||
|  | ||||
| 处理操作超出时间限制 | ||||
|  | ||||
| 0xD0AB | ||||
|  | ||||
| 进程操作中的作业参数无效 | ||||
|  | ||||
| 0xD0AC | ||||
|  | ||||
| 进程操作中的作业数据无效 | ||||
|  | ||||
| 0xD0AD | ||||
|  | ||||
| 已设置操作模式 | ||||
|  | ||||
| 0xD0AE | ||||
|  | ||||
| 作业是通过不同的连接设置的,只能通过此连接进行处理 | ||||
|  | ||||
| 0xD0C1 | ||||
|  | ||||
| 访问标签时至少检测到一个错误 | ||||
|  | ||||
| 0xD0C2 | ||||
|  | ||||
| 切换到STOP / HOLD模式 | ||||
|  | ||||
| 0xD0C3 | ||||
|  | ||||
| 访问标记时至少检测到一个错误。模式更改为STOP / HOLD | ||||
|  | ||||
| 0xD0C4 | ||||
|  | ||||
| 运行时测量期间超时 | ||||
|  | ||||
| 0xD0C5 | ||||
|  | ||||
| 块堆栈的显示不一致,因为块被删除/重新加载 | ||||
|  | ||||
| 0xD0C6 | ||||
|  | ||||
| 作业已被删除,因为它所引用的作业已被删除 | ||||
|  | ||||
| 0xD0C7 | ||||
|  | ||||
| 由于退出了STOP模式,因此作业被自动删除 | ||||
|  | ||||
| 0xD0C8 | ||||
|  | ||||
| 由于测试作业和正在运行的程序之间不一致,“块状态”中止 | ||||
|  | ||||
| 0xD0C9 | ||||
|  | ||||
| 通过复位OB90退出状态区域 | ||||
|  | ||||
| 0xD0CA | ||||
|  | ||||
| 通过在退出前重置OB90并访问错误读取标签退出状态范围 | ||||
|  | ||||
| 0xD0CB | ||||
|  | ||||
| 外设输出的输出禁用再次激活 | ||||
|  | ||||
| 0xD0CC | ||||
|  | ||||
| 调试功能的数据量受时间限制 | ||||
|  | ||||
| 0xD201 | ||||
|  | ||||
| 块名称中的语法错误 | ||||
|  | ||||
| 0xD202 | ||||
|  | ||||
| 函数参数中的语法错误 | ||||
|  | ||||
| 0xD205 | ||||
|  | ||||
| RAM中已存在链接块:无法进行条件复制 | ||||
|  | ||||
| 0xD206 | ||||
|  | ||||
| EPROM中已存在链接块:无法进行条件复制 | ||||
|  | ||||
| 0xD208 | ||||
|  | ||||
| 超出模块的最大复制(未链接)块数 | ||||
|  | ||||
| 0xD209 | ||||
|  | ||||
| (至少)模块上找不到给定块之一 | ||||
|  | ||||
| 0xD20A | ||||
|  | ||||
| 超出了可以与一个作业链接的最大块数 | ||||
|  | ||||
| 0xD20B | ||||
|  | ||||
| 超出了一个作业可以删除的最大块数 | ||||
|  | ||||
| 0xD20C | ||||
|  | ||||
| OB无法复制,因为关联的优先级不存在 | ||||
|  | ||||
| 0xD20D | ||||
|  | ||||
| SDB无法解释(例如,未知数) | ||||
|  | ||||
| 0xD20E | ||||
|  | ||||
| 没有(进一步)阻止可用 | ||||
|  | ||||
| 0xD20F | ||||
|  | ||||
| 超出模块特定的最大块大小 | ||||
|  | ||||
| 0xD210 | ||||
|  | ||||
| 块号无效 | ||||
|  | ||||
| 0xD212 | ||||
|  | ||||
| 标头属性不正确(与运行时相关) | ||||
|  | ||||
| 0xD213 | ||||
|  | ||||
| SDB太多。请注意对正在使用的模块的限制 | ||||
|  | ||||
| 0xD216 | ||||
|  | ||||
| 无效的用户程序 - 重置模块 | ||||
|  | ||||
| 0xD217 | ||||
|  | ||||
| 不允许在模块属性中指定的保护级别 | ||||
|  | ||||
| 0xD218 | ||||
|  | ||||
| 属性不正确(主动/被动) | ||||
|  | ||||
| 0xD219 | ||||
|  | ||||
| 块长度不正确(例如,第一部分或整个块的长度不正确) | ||||
|  | ||||
| 0xD21A | ||||
|  | ||||
| 本地数据长度不正确或写保护错误 | ||||
|  | ||||
| 0xD21B | ||||
|  | ||||
| 模块无法压缩或压缩早期中断 | ||||
|  | ||||
| 0xD21D | ||||
|  | ||||
| 传输的动态项目数据量是非法的 | ||||
|  | ||||
| 0xD21E | ||||
|  | ||||
| 无法为模块(例如FM,CP)分配参数。系统数据无法链接 | ||||
|  | ||||
| 0xD220 | ||||
|  | ||||
| 编程语言无效。请注意对正在使用的模块的限制 | ||||
|  | ||||
| 0xD221 | ||||
|  | ||||
| 连接或路由的系统数据无效 | ||||
|  | ||||
| 0xD222 | ||||
|  | ||||
| 全局数据定义的系统数据包含无效参数 | ||||
|  | ||||
| 0xD223 | ||||
|  | ||||
| 通信功能块的实例数据块错误或超出最大背景数据块数 | ||||
|  | ||||
| 0xD224 | ||||
|  | ||||
| SCAN系统数据块包含无效参数 | ||||
|  | ||||
| 0xD225 | ||||
|  | ||||
| DP系统数据块包含无效参数 | ||||
|  | ||||
| 0xD226 | ||||
|  | ||||
| 块中发生结构错误 | ||||
|  | ||||
| 0xD230 | ||||
|  | ||||
| 块中发生结构错误 | ||||
|  | ||||
| 0xD231 | ||||
|  | ||||
| 至少有一个已加载的OB无法复制,因为关联的优先级不存在 | ||||
|  | ||||
| 0xD232 | ||||
|  | ||||
| 加载块的至少一个块编号是非法的 | ||||
|  | ||||
| 0xD234 | ||||
|  | ||||
| 块在指定的内存介质或作业中存在两次 | ||||
|  | ||||
| 0xD235 | ||||
|  | ||||
| 该块包含不正确的校验和 | ||||
|  | ||||
| 0xD236 | ||||
|  | ||||
| 该块不包含校验和 | ||||
|  | ||||
| 0xD237 | ||||
|  | ||||
| 您将要加载块两次,即CPU上已存在具有相同时间戳的块 | ||||
|  | ||||
| 0xD238 | ||||
|  | ||||
| 指定的块中至少有一个不是DB | ||||
|  | ||||
| 0xD239 | ||||
|  | ||||
| 至少有一个指定的DB在装载存储器中不可用作链接变量 | ||||
|  | ||||
| 0xD23A | ||||
|  | ||||
| 至少有一个指定的DB与复制和链接的变体有很大不同 | ||||
|  | ||||
| 0xD240 | ||||
|  | ||||
| 违反了协调规则 | ||||
|  | ||||
| 0xD241 | ||||
|  | ||||
| 当前保护级别不允许该功能 | ||||
|  | ||||
| 0xD242 | ||||
|  | ||||
| 处理F块时的保护冲突 | ||||
|  | ||||
| 0xD250 | ||||
|  | ||||
| 更新和模块ID或版本不匹配 | ||||
|  | ||||
| 0xD251 | ||||
|  | ||||
| 操作系统组件序列不正确 | ||||
|  | ||||
| 0xD252 | ||||
|  | ||||
| 校验和错误 | ||||
|  | ||||
| 0xD253 | ||||
|  | ||||
| 没有可用的可执行加载程序; 只能使用存储卡进行更新 | ||||
|  | ||||
| 0xD254 | ||||
|  | ||||
| 操作系统中的存储错误 | ||||
|  | ||||
| 0xD280 | ||||
|  | ||||
| 在S7-300 CPU中编译块时出错 | ||||
|  | ||||
| 0xD2A1 | ||||
|  | ||||
| 块上的另一个块功能或触发器处于活动状态 | ||||
|  | ||||
| 0xD2A2 | ||||
|  | ||||
| 块上的触发器处于活动状态。首先完成调试功能 | ||||
|  | ||||
| 0xD2A3 | ||||
|  | ||||
| 块未激活(链接),块被占用或块当前被标记为删除 | ||||
|  | ||||
| 0xD2A4 | ||||
|  | ||||
| 该块已被另一个块函数处理 | ||||
|  | ||||
| 0xD2A6 | ||||
|  | ||||
| 无法同时保存和更改用户程序 | ||||
|  | ||||
| 0xD2A7 | ||||
|  | ||||
| 块具有“未链接”属性或未处理 | ||||
|  | ||||
| 0xD2A8 | ||||
|  | ||||
| 激活的调试功能阻止将参数分配给CPU | ||||
|  | ||||
| 0xD2A9 | ||||
|  | ||||
| 正在为CPU分配新参数 | ||||
|  | ||||
| 0xD2AA | ||||
|  | ||||
| 当前正在为模块分配新参数 | ||||
|  | ||||
| 0xD2AB | ||||
|  | ||||
| 当前正在更改动态配置限制 | ||||
|  | ||||
| 0xD2AC | ||||
|  | ||||
| 正在运行的激活或取消激活分配(SFC 12)暂时阻止R-KiR过程 | ||||
|  | ||||
| 0xD2B0 | ||||
|  | ||||
| 在RUN(CiR)中配置时发生错误 | ||||
|  | ||||
| 0xD2C0 | ||||
|  | ||||
| 已超出最大工艺对象数 | ||||
|  | ||||
| 0xD2C1 | ||||
|  | ||||
| 模块上已存在相同的技术数据块 | ||||
|  | ||||
| 0xD2C2 | ||||
|  | ||||
| 无法下载用户程序或下载硬件配置 | ||||
|  | ||||
| 0xD401 | ||||
|  | ||||
| 信息功能不可用 | ||||
|  | ||||
| 0xD402 | ||||
|  | ||||
| 信息功能不可用 | ||||
|  | ||||
| 0xD403 | ||||
|  | ||||
| 服务已登录/注销(诊断/ PMC) | ||||
|  | ||||
| 0xD404 | ||||
|  | ||||
| 达到的最大节点数。不再需要登录诊断/ PMC | ||||
|  | ||||
| 0xD405 | ||||
|  | ||||
| 不支持服务或函数参数中的语法错误 | ||||
|  | ||||
| 0xD406 | ||||
|  | ||||
| 当前不可用的必需信息 | ||||
|  | ||||
| 0xD407 | ||||
|  | ||||
| 发生诊断错误 | ||||
|  | ||||
| 0xD408 | ||||
|  | ||||
| 更新已中止 | ||||
|  | ||||
| 0xD409 | ||||
|  | ||||
| DP总线错误 | ||||
|  | ||||
| 0xD601 | ||||
|  | ||||
| 函数参数中的语法错误 | ||||
|  | ||||
| 0xD602 | ||||
|  | ||||
| 输入的密码不正确 | ||||
|  | ||||
| 0xD603 | ||||
|  | ||||
| 连接已合法化 | ||||
|  | ||||
| 0xD604 | ||||
|  | ||||
| 已启用连接 | ||||
|  | ||||
| 0xD605 | ||||
|  | ||||
| 由于密码不存在,因此无法进行合法化 | ||||
|  | ||||
| 0xD801 | ||||
|  | ||||
| 至少有一个标记地址无效 | ||||
|  | ||||
| 0xD802 | ||||
|  | ||||
| 指定的作业不存在 | ||||
|  | ||||
| 0xD803 | ||||
|  | ||||
| 非法的工作状态 | ||||
|  | ||||
| 0xD804 | ||||
|  | ||||
| 非法循环时间(非法时基或多个) | ||||
|  | ||||
| 0xD805 | ||||
|  | ||||
| 不能再设置循环读取作业 | ||||
|  | ||||
| 0xD806 | ||||
|  | ||||
| 引用的作业处于无法执行请求的功能的状态 | ||||
|  | ||||
| 0xD807 | ||||
|  | ||||
| 功能因过载而中止,这意味着执行读取周期所需的时间比设置的扫描周期时间长 | ||||
|  | ||||
| 0xDC01 | ||||
|  | ||||
| 日期和/或时间无效 | ||||
|  | ||||
| 0xE201 | ||||
|  | ||||
| CPU已经是主设备 | ||||
|  | ||||
| 0xE202 | ||||
|  | ||||
| 由于闪存模块中的用户程序不同,无法进行连接和更新 | ||||
|  | ||||
| 0xE203 | ||||
|  | ||||
| 由于固件不同,无法连接和更新 | ||||
|  | ||||
| 0xE204 | ||||
|  | ||||
| 由于内存配置不同,无法连接和更新 | ||||
|  | ||||
| 0xE205 | ||||
|  | ||||
| 由于同步错误导致连接/更新中止 | ||||
|  | ||||
| 0xE206 | ||||
|  | ||||
| 由于协调违规而拒绝连接/更新 | ||||
|  | ||||
| 0xEF01 | ||||
|  | ||||
| S7协议错误:ID2错误; 工作中只允许00H | ||||
|  | ||||
| 0xEF02 | ||||
|  | ||||
| S7协议错误:ID2错误; 资源集不存在 | ||||
| @@ -24,7 +24,7 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase | ||||
|     public ReadWriteDevicesSerialSessionBase(SerialSession serialSession) | ||||
|     { | ||||
|         SerialSession = serialSession; | ||||
|         WaitingClientEx = SerialSession.GetWaitingClient(new() { ThrowBreakException = true }); | ||||
|         WaitingClientEx = SerialSession.CreateWaitingClient(new() { }); | ||||
|         SerialSession.Received -= Received; | ||||
|         SerialSession.Connecting -= Connecting; | ||||
|         SerialSession.Connected -= Connected; | ||||
| @@ -96,8 +96,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; | ||||
|             ResponsedData result = SerialSession.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||
|             waitingOptions ??= new WaitingOptions { }; | ||||
|             ResponsedData result = SerialSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||
|             return OperResult.CreateSuccessResult(result.Data); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
| @@ -111,8 +111,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; | ||||
|             ResponsedData result = await SerialSession.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||
|             waitingOptions ??= new WaitingOptions { }; | ||||
|             ResponsedData result = await SerialSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||
|             return OperResult.CreateSuccessResult(result.Data); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|   | ||||
| @@ -23,7 +23,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase | ||||
|     public ReadWriteDevicesTcpClientBase(TcpClient tcpClient) | ||||
|     { | ||||
|         TcpClient = tcpClient; | ||||
|         WaitingClientEx = TcpClient.GetWaitingClient(new() { ThrowBreakException = true }); | ||||
|         WaitingClientEx = TcpClient.CreateWaitingClient(new() { }); | ||||
|         TcpClient.Connecting -= Connecting; | ||||
|         TcpClient.Connected -= Connected; | ||||
|         TcpClient.Disconnecting -= Disconnecting; | ||||
| @@ -86,8 +86,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true, }; | ||||
|             ResponsedData result = TcpClient.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||
|             waitingOptions ??= new WaitingOptions { }; | ||||
|             ResponsedData result = TcpClient.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||
|             return OperResult.CreateSuccessResult(result.Data); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
| @@ -101,8 +101,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; | ||||
|             ResponsedData result = await TcpClient.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||
|             waitingOptions ??= new WaitingOptions { }; | ||||
|             ResponsedData result = await TcpClient.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||
|             return OperResult.CreateSuccessResult(result.Data); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
| @@ -137,13 +137,13 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase | ||||
|  | ||||
|     private Task Disconnected(ITcpClientBase client, DisconnectEventArgs e) | ||||
|     { | ||||
|         Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message); | ||||
|         Logger?.Debug($"{client.IP}:{client.Port}断开连接-{e.Message}"); | ||||
|         return EasyTask.CompletedTask; | ||||
|     } | ||||
|  | ||||
|     private Task Disconnecting(ITcpClientBase client, DisconnectEventArgs e) | ||||
|     { | ||||
|         Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message); | ||||
|         Logger?.Debug($"{client.IP}:{client.Port}正在主动断开连接-{e.Message}"); | ||||
|         return EasyTask.CompletedTask; | ||||
|     } | ||||
| } | ||||
| @@ -101,14 +101,14 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase | ||||
|     /// <param name="e"></param> | ||||
|     protected virtual Task Connected(SocketClient client, ConnectedEventArgs e) | ||||
|     { | ||||
|         Logger?.Debug(client.IP + ":" + client.Port + "连接成功"); | ||||
|         Logger?.Debug($"{client.IP}:{client.Port}连接成功"); | ||||
|         return EasyTask.CompletedTask; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     protected virtual Task Connecting(SocketClient client, ConnectingEventArgs e) | ||||
|     { | ||||
|         Logger?.Debug(client.IP + ":" + client.Port + "正在连接"); | ||||
|         Logger?.Debug($"{client.IP}:{client.Port}正在连接"); | ||||
|         SetDataAdapter(client); | ||||
|         return EasyTask.CompletedTask; | ||||
|     } | ||||
| @@ -116,14 +116,14 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase | ||||
|     /// <inheritdoc/> | ||||
|     protected virtual Task Disconnected(ITcpClientBase client, DisconnectEventArgs e) | ||||
|     { | ||||
|         Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message); | ||||
|         Logger?.Debug($"{client.IP}:{client.Port}断开连接-{e.Message}"); | ||||
|         return EasyTask.CompletedTask; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     protected virtual Task Disconnecting(ITcpClientBase client, DisconnectEventArgs e) | ||||
|     { | ||||
|         Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message); | ||||
|         Logger?.Debug($"{client.IP}:{client.Port}正在主动断开连接-{e.Message}"); | ||||
|         return EasyTask.CompletedTask; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -22,7 +22,7 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase | ||||
|     { | ||||
|         UdpSession = udpSession; | ||||
|         SetDataAdapter(); | ||||
|         WaitingClientEx = UdpSession.GetWaitingClient(new() { ThrowBreakException = true }); | ||||
|         WaitingClientEx = UdpSession.CreateWaitingClient(new() { }); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -64,8 +64,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; | ||||
|             ResponsedData result = UdpSession.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||
|             waitingOptions ??= new WaitingOptions { }; | ||||
|             ResponsedData result = UdpSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||
|             return OperResult.CreateSuccessResult(result.Data); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
| @@ -79,8 +79,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; | ||||
|             ResponsedData result = await UdpSession.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||
|             waitingOptions ??= new WaitingOptions { }; | ||||
|             ResponsedData result = await UdpSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||
|             return OperResult.CreateSuccessResult(result.Data); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|   | ||||
| @@ -20,6 +20,12 @@ public sealed class EasyLock | ||||
|     private static long lockWaitCount; | ||||
|     private readonly SemaphoreSlim m_waiterLock = new SemaphoreSlim(1); | ||||
|     /// <inheritdoc/> | ||||
|     public EasyLock(bool initialState = true) | ||||
|     { | ||||
|         if (!initialState) | ||||
|             m_waiterLock.Wait(); | ||||
|     } | ||||
|     /// <inheritdoc/> | ||||
|     ~EasyLock() | ||||
|     { | ||||
|         m_waiterLock.SafeDispose(); | ||||
| @@ -45,39 +51,41 @@ public sealed class EasyLock | ||||
|     /// <summary> | ||||
|     /// 进入锁 | ||||
|     /// </summary> | ||||
|     public void Wait() | ||||
|     public void Wait(CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         Interlocked.Increment(ref lockWaitCount); | ||||
|         m_waiterLock.Wait(); | ||||
|         m_waiterLock.Wait(cancellationToken); | ||||
|         Interlocked.Decrement(ref lockWaitCount); | ||||
|     } | ||||
|     /// <summary> | ||||
|     /// 进入锁 | ||||
|     /// </summary> | ||||
|     public void Wait(TimeSpan timeSpan, CancellationToken cancellationToken) | ||||
|     public bool Wait(TimeSpan timeSpan, CancellationToken cancellationToken) | ||||
|     { | ||||
|         Interlocked.Increment(ref lockWaitCount); | ||||
|         m_waiterLock.Wait(timeSpan, cancellationToken); | ||||
|         var data = m_waiterLock.Wait(timeSpan, cancellationToken); | ||||
|         Interlocked.Decrement(ref lockWaitCount); | ||||
|         return data; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 进入锁 | ||||
|     /// </summary> | ||||
|     public async Task WaitAsync() | ||||
|     public async Task WaitAsync(CancellationToken cancellationToken = default) | ||||
|     { | ||||
|         Interlocked.Increment(ref lockWaitCount); | ||||
|         await m_waiterLock.WaitAsync(); | ||||
|         await m_waiterLock.WaitAsync(cancellationToken); | ||||
|         Interlocked.Decrement(ref lockWaitCount); | ||||
|     } | ||||
|     /// <summary> | ||||
|     /// 进入锁 | ||||
|     /// </summary> | ||||
|     public async Task WaitAsync(TimeSpan timeSpan, CancellationToken cancellationToken) | ||||
|     public async Task<bool> WaitAsync(TimeSpan timeSpan, CancellationToken cancellationToken) | ||||
|     { | ||||
|         Interlocked.Increment(ref lockWaitCount); | ||||
|         await m_waiterLock.WaitAsync(timeSpan, cancellationToken); | ||||
|         var data = await m_waiterLock.WaitAsync(timeSpan, cancellationToken); | ||||
|         Interlocked.Decrement(ref lockWaitCount); | ||||
|         return data; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -10,6 +10,7 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| using System.Globalization; | ||||
| using System.Net; | ||||
| using System.Text; | ||||
| using System.Text.RegularExpressions; | ||||
| @@ -114,17 +115,47 @@ public static class StringExtensions | ||||
|         else if (propertyType == typeof(sbyte)) | ||||
|             _value = sbyte.Parse(value); | ||||
|         else if (propertyType == typeof(short)) | ||||
|             _value = short.Parse(value); | ||||
|         { | ||||
|             if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) | ||||
|                 _value = short.Parse(value.Substring(2), NumberStyles.HexNumber); | ||||
|             else | ||||
|                 _value = short.Parse(value); | ||||
|         } | ||||
|         else if (propertyType == typeof(ushort)) | ||||
|             _value = ushort.Parse(value); | ||||
|         { | ||||
|             if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) | ||||
|                 _value = ushort.Parse(value.Substring(2), NumberStyles.HexNumber); | ||||
|             else | ||||
|                 _value = ushort.Parse(value); | ||||
|         } | ||||
|         else if (propertyType == typeof(int)) | ||||
|             _value = int.Parse(value); | ||||
|         { | ||||
|             if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) | ||||
|                 _value = int.Parse(value.Substring(2), NumberStyles.HexNumber); | ||||
|             else | ||||
|                 _value = int.Parse(value); | ||||
|         } | ||||
|         else if (propertyType == typeof(uint)) | ||||
|             _value = uint.Parse(value); | ||||
|         { | ||||
|             if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) | ||||
|                 _value = uint.Parse(value.Substring(2), NumberStyles.HexNumber); | ||||
|             else | ||||
|                 _value = uint.Parse(value); | ||||
|         } | ||||
|         else if (propertyType == typeof(long)) | ||||
|             _value = long.Parse(value); | ||||
|         { | ||||
|             if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) | ||||
|                 _value = long.Parse(value.Substring(2), NumberStyles.HexNumber); | ||||
|             else | ||||
|                 _value = long.Parse(value); | ||||
|         } | ||||
|         else if (propertyType == typeof(ulong)) | ||||
|             _value = ulong.Parse(value); | ||||
|         { | ||||
|             if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) | ||||
|                 _value = ulong.Parse(value.Substring(2), NumberStyles.HexNumber); | ||||
|             else | ||||
|                 _value = ulong.Parse(value); | ||||
|         } | ||||
|         else if (propertyType == typeof(float)) | ||||
|             _value = float.Parse(value); | ||||
|         else if (propertyType == typeof(double)) | ||||
| @@ -142,7 +173,6 @@ public static class StringExtensions | ||||
|         else if (propertyType.IsEnum) | ||||
|             _value = Enum.Parse(propertyType, value); | ||||
|         return _value; | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -28,7 +28,7 @@ public class ByteTransformUtil | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             return new OperResult<TResult>(string.Format("{0} {1} : Length({2}) {3}", "转换失败", result.Content.ToHexString(), result.Content.Length, ex.Message)); | ||||
|             return new OperResult<TResult>(string.Format("{0} {1} : Length({2}) {3}", "转换失败", result.Content.ToHexString(), result.Content.Length, ex)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -32,7 +32,7 @@ public static class JTokenUtil | ||||
|         } | ||||
|         catch (Exception) | ||||
|         { | ||||
|             tagValue = JToken.Parse("\"" + item + "\""); | ||||
|             tagValue = JToken.Parse($"\"{item}\""); | ||||
|         } | ||||
|  | ||||
|         return tagValue; | ||||
|   | ||||
| @@ -27,8 +27,7 @@ using System.Runtime.CompilerServices; | ||||
| namespace ThingsGateway.Foundation.Core | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 具有释放的对象。 | ||||
|     /// 并未实现析构函数相关。 | ||||
|     /// 具有释放的对象。内部实现了GC.SuppressFinalize,但不包括析构函数相关。 | ||||
|     /// </summary> | ||||
|     public partial class DisposableObject : IDisposable | ||||
|     { | ||||
| @@ -65,11 +64,12 @@ namespace ThingsGateway.Foundation.Core | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 释放资源。 | ||||
|         /// 释放资源。内部已经处理了<see cref="GC.SuppressFinalize(object)"/> | ||||
|         /// </summary> | ||||
|         public void Dispose() | ||||
|         { | ||||
|             this.Dispose(disposing: true); | ||||
|             GC.SuppressFinalize(this); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -72,7 +72,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|                     } | ||||
|                     catch (Exception ex) | ||||
|                     { | ||||
|                         this.OnError(ex.Message, false, true); | ||||
|                         this.OnError(ex.ToString(), false, true); | ||||
|                     } | ||||
|                 } | ||||
|                 return FilterResult.GoOn; | ||||
| @@ -121,7 +121,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|                         } | ||||
|                         catch (Exception ex) | ||||
|                         { | ||||
|                             this.OnError(ex.Message, false, true); | ||||
|                             this.OnError(ex.ToString(), false, true); | ||||
|                         } | ||||
|                     } | ||||
|                     return FilterResult.GoOn; | ||||
|   | ||||
| @@ -87,7 +87,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 this.OnError(ex.Message); | ||||
|                 this.OnError(ex.ToString()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -182,7 +182,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|             } | ||||
|             if (!flag && !converter.CanConvertTo(destinationType)) | ||||
|             { | ||||
|                 throw new InvalidOperationException("无法转换成类型:" + value.ToString() + "==>" + destinationType); | ||||
|                 throw new InvalidOperationException($"无法转换成类型:{value.ToString()}==>{destinationType}"); | ||||
|             } | ||||
|             try | ||||
|             { | ||||
| @@ -190,7 +190,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 throw new InvalidOperationException(" 类型转换出错:" + value.ToString() + "==>" + destinationType, e); | ||||
|                 throw new InvalidOperationException($" 类型转换出错:{value.ToString()}==>{destinationType}", e); | ||||
|             } | ||||
|             return returnValue; | ||||
|         } | ||||
|   | ||||
| @@ -189,7 +189,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|         /// <returns></returns> | ||||
|         public static IEnumerable<string> GetTupleElementNames(this ParameterInfo parameter) | ||||
|         { | ||||
|             return ((dynamic)parameter.GetCustomAttribute(Type.GetType("System.Runtime.CompilerServices.TupleElementNamesAttribute")))?.TransformNames; | ||||
|             return (IEnumerable<string>)DynamicMethodMemberAccessor.Default.GetValue(parameter.GetCustomAttribute(Type.GetType("System.Runtime.CompilerServices.TupleElementNamesAttribute")), "TransformNames"); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -199,7 +199,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|         /// <returns></returns> | ||||
|         public static IEnumerable<string> GetTupleElementNames(this MemberInfo memberInfo) | ||||
|         { | ||||
|             return ((dynamic)memberInfo.GetCustomAttribute(Type.GetType("System.Runtime.CompilerServices.TupleElementNamesAttribute")))?.TransformNames; | ||||
|             return (IEnumerable<string>)DynamicMethodMemberAccessor.Default.GetValue(memberInfo.GetCustomAttribute(Type.GetType("System.Runtime.CompilerServices.TupleElementNamesAttribute")), "TransformNames"); | ||||
|         } | ||||
|         #endregion | ||||
|  | ||||
|   | ||||
| @@ -23,6 +23,8 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System.Runtime.CompilerServices; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Core | ||||
| { | ||||
|     /// <summary> | ||||
| @@ -49,5 +51,27 @@ namespace ThingsGateway.Foundation.Core | ||||
|         { | ||||
|             task.ConfigureAwait(false).GetAwaiter().GetResult(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 配置ConfigureAwait为false。 | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T"></typeparam> | ||||
|         /// <param name="task"></param> | ||||
|         /// <returns></returns> | ||||
|         public static ConfiguredTaskAwaitable<T> ConfigureFalseAwait<T>(this Task<T> task) | ||||
|         { | ||||
|             return task.ConfigureAwait(false); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 配置ConfigureAwait为false。 | ||||
|         /// </summary> | ||||
|         /// <param name="task"></param> | ||||
|         public static ConfiguredTaskAwaitable ConfigureFalseAwait(this Task task) | ||||
|         { | ||||
|             return task.ConfigureAwait(false); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -70,6 +70,15 @@ namespace ThingsGateway.Foundation.Core | ||||
|             return isPeriod; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 累计增加一个计数 | ||||
|         /// </summary> | ||||
|         /// <returns></returns> | ||||
|         public bool Increment() | ||||
|         { | ||||
|             return this.Increment(1); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 重置<see cref="Count"/>和<see cref="LastIncrement"/> | ||||
|         /// </summary> | ||||
|   | ||||
| @@ -47,14 +47,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|         /// </summary> | ||||
|         public TimeSpan Period { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 重置<see cref="Count"/>和<see cref="LastIncrement"/> | ||||
|         /// </summary> | ||||
|         public void Reset() | ||||
|         { | ||||
|             this.m_count = 0; | ||||
|             this.m_lastIncrement = default; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 累计增加计数 | ||||
| @@ -78,5 +71,26 @@ namespace ThingsGateway.Foundation.Core | ||||
|             Interlocked.Add(ref this.m_count, value); | ||||
|             return isPeriod; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 累计增加一个计数 | ||||
|         /// </summary> | ||||
|         /// <returns></returns> | ||||
|         public bool Increment() | ||||
|         { | ||||
|             return this.Increment(1); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 重置<see cref="Count"/>和<see cref="LastIncrement"/> | ||||
|         /// </summary> | ||||
|         public void Reset() | ||||
|         { | ||||
|             this.m_count = 0; | ||||
|             this.m_lastIncrement = default; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -133,7 +133,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 fileStorage = null; | ||||
|                 msg = ex.Message; | ||||
|                 msg = ex.ToString(); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -134,7 +134,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|                         string path = null; | ||||
|                         while (true) | ||||
|                         { | ||||
|                             path = Path.Combine(dir, $"{count:0000}" + ".log"); | ||||
|                             path = Path.Combine(dir, $"{count:0000}.log"); | ||||
|                             if (!File.Exists(path)) | ||||
|                             { | ||||
|                                 this.m_writer = FilePool.GetWriter(path); | ||||
|   | ||||
| @@ -292,7 +292,13 @@ public static class LoggerExtensions | ||||
|     { | ||||
|         logger.Log(ThingsGateway.Foundation.Core.LogLevel.Error, null, msg, ex); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 输出错误日志 | ||||
|     /// </summary> | ||||
|     public static void LogError(this ILog logger, Exception ex) | ||||
|     { | ||||
|         logger.Log(ThingsGateway.Foundation.Core.LogLevel.Error, null, ex.Message, ex); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 输出警示日志 | ||||
| @@ -301,7 +307,13 @@ public static class LoggerExtensions | ||||
|     { | ||||
|         logger.Log(ThingsGateway.Foundation.Core.LogLevel.Warning, null, msg, ex); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 输出警示日志 | ||||
|     /// </summary> | ||||
|     public static void LogWarning(this ILog logger, Exception ex) | ||||
|     { | ||||
|         logger.Log(ThingsGateway.Foundation.Core.LogLevel.Warning, null, ex.Message, ex); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 输出警示日志 | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| #endregion | ||||
|  | ||||
| using System.Diagnostics; | ||||
| using System.Runtime.CompilerServices; | ||||
|  | ||||
| #if NET6_0_OR_GREATER | ||||
| using System.Numerics; | ||||
| @@ -55,12 +56,11 @@ namespace ThingsGateway.Foundation.Core | ||||
|             } | ||||
|  | ||||
|             var capacity = 0L; | ||||
|             var poolId = this.Id; | ||||
|             var maxBuckets = SelectBucketIndex(maxArrayLength); | ||||
|             var buckets = new Bucket[maxBuckets + 1]; | ||||
|             for (var i = 0; i < buckets.Length; i++) | ||||
|             { | ||||
|                 buckets[i] = new Bucket(GetMaxSizeForBucket(i), maxArraysPerBucket, poolId); | ||||
|                 buckets[i] = new Bucket(GetMaxSizeForBucket(i), maxArraysPerBucket); | ||||
|                 long num = GetMaxSizeForBucket(i) * maxArraysPerBucket; | ||||
|                 capacity += num; | ||||
|             } | ||||
| @@ -183,16 +183,19 @@ namespace ThingsGateway.Foundation.Core | ||||
|         /// </summary> | ||||
|         /// <param name="size"></param> | ||||
|         /// <returns></returns> | ||||
|         [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||
|         public static int HitSize(int size) | ||||
|         { | ||||
|             return GetMaxSizeForBucket(SelectBucketIndex(size)); | ||||
|         } | ||||
|  | ||||
|         [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||
|         internal static int GetMaxSizeForBucket(int binIndex) | ||||
|         { | ||||
|             return 16 << binIndex; | ||||
|         } | ||||
|  | ||||
|         [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||
|         internal static int SelectBucketIndex(int bufferSize) | ||||
|         { | ||||
| #if NET6_0_OR_GREATER | ||||
| @@ -208,18 +211,16 @@ namespace ThingsGateway.Foundation.Core | ||||
|             internal readonly int m_bufferLength; | ||||
|             private readonly int m_numberOfBuffers; | ||||
|             private T[][] m_buffers; | ||||
|             private readonly int m_poolId; | ||||
|  | ||||
|             private int m_index; | ||||
|             private SpinLock m_lock; | ||||
|  | ||||
|             internal Bucket(int bufferLength, int numberOfBuffers, int poolId) | ||||
|             internal Bucket(int bufferLength, int numberOfBuffers) | ||||
|             { | ||||
|                 this.m_lock = new SpinLock(Debugger.IsAttached); | ||||
|                 this.m_buffers = new T[numberOfBuffers][]; | ||||
|                 this.m_bufferLength = bufferLength; | ||||
|                 this.m_numberOfBuffers = numberOfBuffers; | ||||
|                 this.m_poolId = poolId; | ||||
|             } | ||||
|  | ||||
|             public void Clear() | ||||
|   | ||||
| @@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Core | ||||
|     /// <summary> | ||||
|     /// 内存池 | ||||
|     /// </summary> | ||||
|     public class BytePool : ArrayPool<byte> | ||||
|     public sealed class BytePool : ArrayPool<byte> | ||||
|     { | ||||
|         private readonly Timer m_timer; | ||||
|  | ||||
|   | ||||
| @@ -27,43 +27,48 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <summary> | ||||
|         /// 请求关闭 | ||||
|         /// </summary> | ||||
|         public Action<DmtpActor, string> OnClose { get; set; } | ||||
|         public Func<DmtpActor, string, Task> Closed { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当创建通道时 | ||||
|         /// </summary> | ||||
|         public Action<DmtpActor, CreateChannelEventArgs> OnCreateChannel { get; set; } | ||||
|         public Func<DmtpActor, CreateChannelEventArgs, Task> CreatedChannel { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 查找其他IDmtpActor | ||||
|         /// </summary> | ||||
|         public Func<string, IDmtpActor> OnFindDmtpActor { get; set; } | ||||
|         public Func<string, Task<IDmtpActor>> FindDmtpActor { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在完成握手连接时 | ||||
|         /// </summary> | ||||
|         public Action<DmtpActor, DmtpVerifyEventArgs> OnHandshaked { get; set; } | ||||
|         public Func<DmtpActor, DmtpVerifyEventArgs, Task> Handshaked { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 握手 | ||||
|         /// </summary> | ||||
|         public Action<DmtpActor, DmtpVerifyEventArgs> OnHandshaking { get; set; } | ||||
|         public Func<DmtpActor, DmtpVerifyEventArgs, Task> Handshaking { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 重设Id | ||||
|         /// </summary> | ||||
|         public Action<DmtpActor, WaitSetId> OnResetId { get; set; } | ||||
|         public Func<DmtpActor, IdChangedEventArgs, Task> IdChanged { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当需要路由的时候 | ||||
|         /// </summary> | ||||
|         public Action<DmtpActor, PackageRouterEventArgs> OnRouting { get; set; } | ||||
|         public Func<DmtpActor, PackageRouterEventArgs, Task> Routing { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 发送数据接口 | ||||
|         /// </summary> | ||||
|         public Action<DmtpActor, ArraySegment<byte>[]> OutputSend { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 异步发送数据接口 | ||||
|         /// </summary> | ||||
|         public Func<DmtpActor, ArraySegment<byte>[], Task> OutputSendAsync { get; set; } | ||||
|  | ||||
|         #endregion 委托 | ||||
|  | ||||
|         #region 属性 | ||||
| @@ -118,32 +123,6 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual void Close(bool sendClose, string message) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (this.IsHandshaked) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         if (sendClose) | ||||
|                         { | ||||
|                             this.SendString(0, message); | ||||
|                         } | ||||
|                     } | ||||
|                     catch | ||||
|                     { | ||||
|                     } | ||||
|                     this.IsHandshaked = false; | ||||
|                     this.WaitHandlePool.CancelAll(); | ||||
|                     this.OnClose?.Invoke(this, message); | ||||
|                 } | ||||
|             } | ||||
|             catch | ||||
|             { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 建立对点 | ||||
| @@ -165,7 +144,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 Metadata = metadata | ||||
|             }; | ||||
|  | ||||
|             this.OnHandshaking?.Invoke(this, args); | ||||
|             this.OnHandshaking(args).GetFalseAwaitResult(); | ||||
|  | ||||
|             var waitVerify = new WaitVerify() | ||||
|             { | ||||
| @@ -189,7 +168,8 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             { | ||||
|                                 this.Id = verifyResult.Id; | ||||
|                                 this.IsHandshaked = true; | ||||
|                                 this.PrivateHandshaked(new DmtpVerifyEventArgs() | ||||
|  | ||||
|                                 Task.Factory.StartNew(this.PrivateOnHandshaked, new DmtpVerifyEventArgs() | ||||
|                                 { | ||||
|                                     Id = verifyResult.Id, | ||||
|                                     Metadata = verifyResult.Metadata, | ||||
| @@ -201,18 +181,15 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             else | ||||
|                             { | ||||
|                                 verifyResult.Handle = true; | ||||
|                                 this.Close(false, verifyResult.Message); | ||||
|                                 throw new TokenVerifyException(verifyResult.Message); | ||||
|                             } | ||||
|                         } | ||||
|                     case WaitDataStatus.Overtime: | ||||
|                         this.Close(false, TouchSocketDmtpStatus.Overtime.GetDescription()); | ||||
|                         throw new TimeoutException(TouchSocketDmtpStatus.Overtime.GetDescription()); | ||||
|                     case WaitDataStatus.Canceled: | ||||
|                     case WaitDataStatus.Disposed: | ||||
|                     default: | ||||
|                         this.Close(false, null); | ||||
|                         return; | ||||
|                         throw new OperationCanceledException(); | ||||
|                 } | ||||
|             } | ||||
|             finally | ||||
| @@ -240,7 +217,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 Metadata = metadata | ||||
|             }; | ||||
|  | ||||
|             this.OnHandshaking?.Invoke(this, args); | ||||
|             await this.OnHandshaking(args).ConfigureFalseAwait(); | ||||
|  | ||||
|             var waitVerify = new WaitVerify() | ||||
|             { | ||||
| @@ -253,8 +230,8 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 this.SendJsonObject(P1_Handshake_Request, waitVerify); | ||||
|                 switch (await waitData.WaitAsync(timeout)) | ||||
|                 await this.SendJsonObjectAsync(P1_Handshake_Request, waitVerify).ConfigureFalseAwait(); | ||||
|                 switch (await waitData.WaitAsync(timeout).ConfigureFalseAwait()) | ||||
|                 { | ||||
|                     case WaitDataStatus.SetRunning: | ||||
|                         { | ||||
| @@ -263,7 +240,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             { | ||||
|                                 this.Id = verifyResult.Id; | ||||
|                                 this.IsHandshaked = true; | ||||
|                                 this.PrivateHandshaked(new DmtpVerifyEventArgs() | ||||
|                                 _ = Task.Factory.StartNew(this.PrivateOnHandshaked, new DmtpVerifyEventArgs() | ||||
|                                 { | ||||
|                                     Id = verifyResult.Id, | ||||
|                                     Metadata = verifyResult.Metadata, | ||||
| @@ -275,18 +252,15 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             else | ||||
|                             { | ||||
|                                 verifyResult.Handle = true; | ||||
|                                 this.Close(false, verifyResult.Message); | ||||
|                                 throw new TokenVerifyException(verifyResult.Message); | ||||
|                             } | ||||
|                         } | ||||
|                     case WaitDataStatus.Overtime: | ||||
|                         this.Close(false, TouchSocketDmtpStatus.Overtime.GetDescription()); | ||||
|                         throw new TimeoutException(TouchSocketDmtpStatus.Overtime.GetDescription()); | ||||
|                     case WaitDataStatus.Canceled: | ||||
|                     case WaitDataStatus.Disposed: | ||||
|                     default: | ||||
|                         this.Close(false, null); | ||||
|                         return; | ||||
|                         throw new OperationCanceledException(); | ||||
|                 } | ||||
|             } | ||||
|             finally | ||||
| @@ -295,6 +269,100 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #region 委托触发 | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当关闭后 | ||||
|         /// </summary> | ||||
|         /// <param name="manual"></param> | ||||
|         /// <param name="msg"></param> | ||||
|         protected virtual Task OnClosed(bool manual, string msg) | ||||
|         { | ||||
|             if (this.IsHandshaked) | ||||
|             { | ||||
|                 this.IsHandshaked = false; | ||||
|                 this.WaitHandlePool.CancelAll(); | ||||
|             } | ||||
|  | ||||
|             if (manual) | ||||
|             { | ||||
|                 return EasyTask.CompletedTask; | ||||
|             } | ||||
|             if (this.Closed != null) | ||||
|             { | ||||
|                 return this.Closed.Invoke(this, msg); | ||||
|             } | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 正在握手连接 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         /// <returns></returns> | ||||
|         protected virtual Task OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (this.Handshaking != null) | ||||
|             { | ||||
|                 return this.Handshaking.Invoke(this, e); | ||||
|             } | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 握手连接完成 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         /// <returns></returns> | ||||
|         protected virtual Task OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (this.Handshaked != null) | ||||
|             { | ||||
|                 return this.Handshaked.Invoke(this, e); | ||||
|             } | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当Id修改时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         /// <returns></returns> | ||||
|         protected virtual Task OnIdChanged(IdChangedEventArgs e) | ||||
|         { | ||||
|             if (this.IdChanged != null) | ||||
|             { | ||||
|                 return this.IdChanged.Invoke(this, e); | ||||
|             } | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当完成创建通道时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         /// <returns></returns> | ||||
|         protected virtual Task OnCreatedChannel(CreateChannelEventArgs e) | ||||
|         { | ||||
|             if (this.CreatedChannel != null) | ||||
|             { | ||||
|                 return this.CreatedChannel.Invoke(this, e); | ||||
|             } | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private void PrivateOnHandshaked(object obj) | ||||
|         { | ||||
|             this.OnHandshaked((DmtpVerifyEventArgs)obj); | ||||
|         } | ||||
|  | ||||
|         private void PrivateOnCreatedChannel(object obj) | ||||
|         { | ||||
|             this.OnCreatedChannel((CreateChannelEventArgs)obj); | ||||
|         } | ||||
|         #endregion | ||||
|  | ||||
|         #region const | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -368,7 +436,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// </summary> | ||||
|         /// <param name="message"></param> | ||||
|         /// <returns></returns> | ||||
|         public virtual bool InputReceivedData(DmtpMessage message) | ||||
|         public virtual async Task<bool> InputReceivedData(DmtpMessage message) | ||||
|         { | ||||
|             this.LastActiveTime = DateTime.Now; | ||||
|             var byteBlock = message.BodyByteBlock; | ||||
| @@ -376,7 +444,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             { | ||||
|                 case P0_Close: | ||||
|                     { | ||||
|                         this.Close(false, message.GetBodyString()); | ||||
|                         _ = this.OnClosed(false, message.GetBodyString()); | ||||
|                         return true; | ||||
|                     } | ||||
|                 case P1_Handshake_Request: | ||||
| @@ -391,11 +459,11 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                                 Metadata = waitVerify.Metadata, | ||||
|                                 Id = waitVerify.Id, | ||||
|                             }; | ||||
|                             this.OnHandshaking?.Invoke(this, args); | ||||
|                             await this.OnHandshaking(args).ConfigureFalseAwait(); | ||||
|  | ||||
|                             if (args.Id.HasValue()) | ||||
|                             { | ||||
|                                 this.OnResetId?.Invoke(this, new WaitSetId(this.Id, args.Id)); | ||||
|                                 await this.OnIdChanged(new IdChangedEventArgs(this.Id, args.Id)).ConfigureFalseAwait(); | ||||
|                                 this.Id = args.Id; | ||||
|                             } | ||||
|  | ||||
| @@ -403,24 +471,23 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             { | ||||
|                                 waitVerify.Id = this.Id; | ||||
|                                 waitVerify.Status = 1; | ||||
|                                 this.SendJsonObject(P2_Handshake_Response, waitVerify); | ||||
|                                 await this.SendJsonObjectAsync(P2_Handshake_Response, waitVerify).ConfigureFalseAwait(); | ||||
|                                 this.IsHandshaked = true; | ||||
|                                 args.Message = "Success"; | ||||
|  | ||||
|                                 Task.Factory.StartNew(this.PrivateHandshaked, args); | ||||
|                                 _ = Task.Factory.StartNew(this.PrivateOnHandshaked, args); | ||||
|                             } | ||||
|                             else//不允许连接 | ||||
|                             { | ||||
|                                 waitVerify.Status = 2; | ||||
|                                 waitVerify.Message = args.Message; | ||||
|                                 this.SendJsonObject(P2_Handshake_Response, waitVerify); | ||||
|                                 this.Close(false, args.Message); | ||||
|                                 await this.SendJsonObjectAsync(P2_Handshake_Response, waitVerify).ConfigureFalseAwait(); | ||||
|                                 _ = this.OnClosed(false, args.Message); | ||||
|                             } | ||||
|                         } | ||||
|                         catch (Exception ex) | ||||
|                         { | ||||
|                             this.Logger.Error(this, $"在protocol={message.ProtocolFlags}中发生错误。信息:{ex.Message}"); | ||||
|                             this.Close(false, ex.Message); | ||||
|                             _ = this.OnClosed(false, ex.Message); | ||||
|                         } | ||||
|                         return true; | ||||
|                     } | ||||
| @@ -449,7 +516,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             var waitSetId = this.ResolveJsonObject<WaitSetId>(message.GetBodyString()); | ||||
|                             try | ||||
|                             { | ||||
|                                 this.OnResetId?.Invoke(this, waitSetId); | ||||
|                                 await this.OnIdChanged(new IdChangedEventArgs(waitSetId.OldId, waitSetId.NewId)).ConfigureFalseAwait(); | ||||
|                                 this.Id = waitSetId.NewId; | ||||
|                                 waitSetId.Status = 1; | ||||
|                             } | ||||
| @@ -458,7 +525,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                                 waitSetId.Status = 2; | ||||
|                                 waitSetId.Message = ex.Message; | ||||
|                             } | ||||
|                             this.SendJsonObject(P4_ResetId_Response, waitSetId); | ||||
|                             await this.SendJsonObjectAsync(P4_ResetId_Response, waitSetId).ConfigureFalseAwait(); | ||||
|                         } | ||||
|                         catch (Exception ex) | ||||
|                         { | ||||
| @@ -486,11 +553,12 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|                             if (this.AllowRoute && waitPing.Route) | ||||
|                             { | ||||
|                                 if (this.TryRoute(RouteType.Ping, waitPing)) | ||||
|  | ||||
|                                 if (await this.TryRoute(new PackageRouterEventArgs(RouteType.Ping, waitPing)).ConfigureFalseAwait()) | ||||
|                                 { | ||||
|                                     if (this.TryFindDmtpActor(waitPing.TargetId, out var actor)) | ||||
|                                     if (await this.TryFindDmtpActor(waitPing.TargetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|                                     { | ||||
|                                         actor.Send(P5_Ping_Request, byteBlock); | ||||
|                                         await actor.SendAsync(P5_Ping_Request, byteBlock).ConfigureFalseAwait(); | ||||
|                                         return true; | ||||
|                                     } | ||||
|                                     else | ||||
| @@ -508,7 +576,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                                 waitPing.Status = TouchSocketDmtpStatus.Success.ToValue(); | ||||
|                             } | ||||
|                             waitPing.SwitchId(); | ||||
|                             this.SendJsonObject(P6_Ping_Response, waitPing); | ||||
|                             await this.SendJsonObjectAsync(P6_Ping_Response, waitPing).ConfigureFalseAwait(); | ||||
|                         } | ||||
|                         catch (Exception ex) | ||||
|                         { | ||||
| @@ -524,9 +592,9 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|                             if (this.AllowRoute && waitPing.Route) | ||||
|                             { | ||||
|                                 if (this.TryFindDmtpActor(waitPing.TargetId, out var actor)) | ||||
|                                 if (await this.TryFindDmtpActor(waitPing.TargetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|                                 { | ||||
|                                     actor.Send(P6_Ping_Response, byteBlock); | ||||
|                                     await actor.SendAsync(P6_Ping_Response, byteBlock).ConfigureFalseAwait(); | ||||
|                                 } | ||||
|                             } | ||||
|                             else | ||||
| @@ -548,11 +616,11 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             waitCreateChannel.UnpackageRouter(byteBlock); | ||||
|                             if (this.AllowRoute && waitCreateChannel.Route) | ||||
|                             { | ||||
|                                 if (this.TryRoute(RouteType.CreateChannel, waitCreateChannel)) | ||||
|                                 if (await this.TryRoute(new PackageRouterEventArgs(RouteType.CreateChannel, waitCreateChannel)).ConfigureFalseAwait()) | ||||
|                                 { | ||||
|                                     if (this.TryFindDmtpActor(waitCreateChannel.TargetId, out var actor)) | ||||
|                                     if (await this.TryFindDmtpActor(waitCreateChannel.TargetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|                                     { | ||||
|                                         actor.Send(P7_CreateChannel_Request, byteBlock); | ||||
|                                         await actor.SendAsync(P7_CreateChannel_Request, byteBlock).ConfigureFalseAwait(); | ||||
|                                         return true; | ||||
|                                     } | ||||
|                                     else | ||||
| @@ -593,7 +661,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             waitCreateChannel.SwitchId(); | ||||
|                             byteBlock.Reset(); | ||||
|                             waitCreateChannel.Package(byteBlock); | ||||
|                             this.Send(P8_CreateChannel_Response, byteBlock); | ||||
|                             await this.SendAsync(P8_CreateChannel_Response, byteBlock).ConfigureFalseAwait(); | ||||
|                         } | ||||
|                         catch (Exception ex) | ||||
|                         { | ||||
| @@ -609,9 +677,9 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             waitCreateChannel.UnpackageRouter(byteBlock); | ||||
|                             if (this.AllowRoute && waitCreateChannel.Route) | ||||
|                             { | ||||
|                                 if (this.TryFindDmtpActor(waitCreateChannel.TargetId, out var actor)) | ||||
|                                 if (await this.TryFindDmtpActor(waitCreateChannel.TargetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|                                 { | ||||
|                                     actor.Send(P8_CreateChannel_Response, byteBlock); | ||||
|                                     await actor.SendAsync(P8_CreateChannel_Response, byteBlock).ConfigureFalseAwait(); | ||||
|                                     return true; | ||||
|                                 } | ||||
|                             } | ||||
| @@ -635,9 +703,9 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                             channelPackage.UnpackageRouter(byteBlock); | ||||
|                             if (this.AllowRoute && channelPackage.Route) | ||||
|                             { | ||||
|                                 if (this.TryFindDmtpActor(channelPackage.TargetId, out var actor)) | ||||
|                                 if (await this.TryFindDmtpActor(channelPackage.TargetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|                                 { | ||||
|                                     actor.Send(P9_ChannelPackage, byteBlock); | ||||
|                                     await actor.SendAsync(P9_ChannelPackage, byteBlock).ConfigureFalseAwait(); | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
| @@ -648,7 +716,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                                     channelPackage.DataType = ChannelDataType.DisposeOrder; | ||||
|                                     byteBlock.Reset(); | ||||
|                                     channelPackage.Package(byteBlock); | ||||
|                                     this.Send(P9_ChannelPackage, byteBlock); | ||||
|                                     await this.SendAsync(P9_ChannelPackage, byteBlock).ConfigureFalseAwait(); | ||||
|                                 } | ||||
|                             } | ||||
|                             else | ||||
| @@ -683,7 +751,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <inheritdoc/> | ||||
|         public virtual bool Ping(string targetId, int timeout = 5000) | ||||
|         { | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor)) | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId).GetFalseAwaitResult() is DmtpActor actor) | ||||
|             { | ||||
|                 return actor.Ping(timeout); | ||||
|             } | ||||
| @@ -697,15 +765,15 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual Task<bool> PingAsync(string targetId, int timeout = 5000) | ||||
|         public virtual async Task<bool> PingAsync(string targetId, int timeout = 5000) | ||||
|         { | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor)) | ||||
|             if (this.AllowRoute && await this.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|             { | ||||
|                 return actor.PingAsync(timeout); | ||||
|                 return await actor.PingAsync(timeout).ConfigureFalseAwait(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return this.PrivatePingAsync(targetId, timeout); | ||||
|                 return await this.PrivatePingAsync(targetId, timeout).ConfigureFalseAwait(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -724,7 +792,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                     { | ||||
|                         if (waitData.WaitResult.Status == 1) | ||||
|                         { | ||||
|                             this.OnResetId?.Invoke(this, new WaitSetId(this.Id, id)); | ||||
|                             this.OnIdChanged(new IdChangedEventArgs(this.Id, id)).GetFalseAwaitResult(); | ||||
|                             this.Id = id; | ||||
|                         } | ||||
|                         else | ||||
| @@ -754,13 +822,13 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|             this.SendJsonObject(P3_ResetId_Request, waitSetId); | ||||
|  | ||||
|             switch (await waitData.WaitAsync(5000)) | ||||
|             switch (await waitData.WaitAsync(5000).ConfigureFalseAwait()) | ||||
|             { | ||||
|                 case WaitDataStatus.SetRunning: | ||||
|                     { | ||||
|                         if (waitData.WaitResult.Status == 1) | ||||
|                         { | ||||
|                             this.OnResetId?.Invoke(this, new WaitSetId(this.Id, id)); | ||||
|                             await this.OnIdChanged(new IdChangedEventArgs(this.Id, id)).ConfigureFalseAwait(); | ||||
|                             this.Id = id; | ||||
|                         } | ||||
|                         else | ||||
| @@ -801,6 +869,17 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             this.Send(protocol, bytes, 0, bytes.Length); | ||||
|         } | ||||
|  | ||||
|         private Task SendJsonObjectAsync<T>(ushort protocol, in T obj) | ||||
|         { | ||||
| #if NET6_0_OR_GREATER | ||||
|             var bytes = System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(obj, typeof(T), TouchSokcetDmtpSourceGenerationContext.Default); | ||||
| #else | ||||
|             var bytes = SerializeConvert.JsonSerializeToBytes(obj); | ||||
| #endif | ||||
|  | ||||
|             return this.SendAsync(protocol, bytes, 0, bytes.Length); | ||||
|         } | ||||
|  | ||||
|         private T ResolveJsonObject<T>(string json) | ||||
|         { | ||||
| #if NET6_0_OR_GREATER | ||||
| @@ -836,31 +915,34 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual bool TryFindDmtpActor(string targetId, out DmtpActor actor) | ||||
|         public virtual async Task<DmtpActor> TryFindDmtpActor(string targetId) | ||||
|         { | ||||
|             if (targetId == this.Id) | ||||
|             { | ||||
|                 actor = this; | ||||
|                 return true; | ||||
|                 return this; | ||||
|             } | ||||
|             if (this.OnFindDmtpActor?.Invoke(targetId) is DmtpActor newActor) | ||||
|             if (this.FindDmtpActor != null) | ||||
|             { | ||||
|                 actor = newActor; | ||||
|                 return true; | ||||
|                 if (await this.FindDmtpActor.Invoke(targetId).ConfigureFalseAwait() is DmtpActor newActor) | ||||
|                 { | ||||
|                     return newActor; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             actor = default; | ||||
|             return false; | ||||
|             return default; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual bool TryRoute(RouteType routerType, RouterPackage routerPackage) | ||||
|         public virtual async Task<bool> TryRoute(PackageRouterEventArgs e) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var args = new PackageRouterEventArgs(routerType, routerPackage); | ||||
|                 this.OnRouting?.Invoke(this, args); | ||||
|                 return args.IsPermitOperation; | ||||
|                 if (this.Routing != null) | ||||
|                 { | ||||
|                     await this.Routing.Invoke(this, e).ConfigureFalseAwait(); | ||||
|                     return e.IsPermitOperation; | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
|             catch | ||||
|             { | ||||
| @@ -868,27 +950,6 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual bool TryRoute(RouteType routerType, WaitRouterPackage routerPackage) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var args = new PackageRouterEventArgs(routerType, routerPackage); | ||||
|                 this.OnRouting?.Invoke(this, args); | ||||
|                 routerPackage.Message = args.Message; | ||||
|                 return args.IsPermitOperation; | ||||
|             } | ||||
|             catch | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void PrivateHandshaked(object obj) | ||||
|         { | ||||
|             this.OnHandshaked?.Invoke(this, (DmtpVerifyEventArgs)obj); | ||||
|         } | ||||
|  | ||||
|         private bool PrivatePing(string targetId, int timeout) | ||||
|         { | ||||
|             var waitPing = new WaitPing | ||||
| @@ -942,7 +1003,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             try | ||||
|             { | ||||
|                 this.SendJsonObject(P5_Ping_Request, waitPing); | ||||
|                 switch (await waitData.WaitAsync(timeout)) | ||||
|                 switch (await waitData.WaitAsync(timeout).ConfigureFalseAwait()) | ||||
|                 { | ||||
|                     case WaitDataStatus.SetRunning: | ||||
|                         { | ||||
| @@ -971,7 +1032,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #region 重写 | ||||
|         #region 断开 | ||||
|  | ||||
|         /// <summary> | ||||
|         /// <inheritdoc/> | ||||
| @@ -979,19 +1040,36 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <param name="disposing"></param> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             this.OnClose = null; | ||||
|             this.OnRouting = null; | ||||
|             this.OnFindDmtpActor = null; | ||||
|             this.OnHandshaked = null; | ||||
|             this.OnHandshaking = null; | ||||
|             this.OnResetId = null; | ||||
|  | ||||
|             this.Closed = null; | ||||
|             this.Routing = null; | ||||
|             this.FindDmtpActor = null; | ||||
|             this.Handshaked = null; | ||||
|             this.Handshaking = null; | ||||
|             this.IdChanged = null; | ||||
|             this.OutputSend = null; | ||||
|             this.OnClosed(true, nameof(Dispose)); | ||||
|             this.WaitHandlePool.SafeDispose(); | ||||
|             this.Close(false, nameof(Dispose)); | ||||
|             base.Dispose(disposing); | ||||
|         } | ||||
|         /// <inheritdoc/> | ||||
|         public void Close(string msg) | ||||
|         { | ||||
|             this.OnClosed(true, msg); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool SendClose(string msg) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 this.SendString(0, msg); | ||||
|                 return true; | ||||
|             } | ||||
|             catch | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         #endregion 重写 | ||||
|  | ||||
|         #region 协议同步发送 | ||||
| @@ -1005,7 +1083,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             new ArraySegment<byte>(TouchSocketBitConverter.BigEndian.GetBytes(length)), | ||||
|             new ArraySegment<byte>(buffer,offset,length) | ||||
|            }; | ||||
|             this.OutputSend?.Invoke(this, transferBytes); | ||||
|             this.OutputSend.Invoke(this, transferBytes); | ||||
|             this.LastActiveTime = DateTime.Now; | ||||
|         } | ||||
|  | ||||
| @@ -1022,10 +1100,20 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <inheritdoc/> | ||||
|         public virtual Task SendAsync(ushort protocol, byte[] buffer, int offset, int length) | ||||
|         { | ||||
|             return Task.Run(() => | ||||
|             var transferBytes = new ArraySegment<byte>[] | ||||
|             { | ||||
|                 this.Send(protocol, buffer, offset, length); | ||||
|             }); | ||||
|             new ArraySegment<byte>(TouchSocketBitConverter.BigEndian.GetBytes(protocol)), | ||||
|             new ArraySegment<byte>(TouchSocketBitConverter.BigEndian.GetBytes(length)), | ||||
|             new ArraySegment<byte>(buffer,offset,length) | ||||
|             }; | ||||
|             this.LastActiveTime = DateTime.Now; | ||||
|             return this.OutputSendAsync.Invoke(this, transferBytes); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual Task SendAsync(ushort protocol, ByteBlock byteBlock) | ||||
|         { | ||||
|             return this.SendAsync(protocol, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|         } | ||||
|  | ||||
|         #endregion 协议异步发送 | ||||
| @@ -1059,7 +1147,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             { | ||||
|                 throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId)); | ||||
|             } | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor)) | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId).GetFalseAwaitResult() is DmtpActor actor) | ||||
|             { | ||||
|                 return actor.CreateChannel(id, metadata); | ||||
|             } | ||||
| @@ -1077,7 +1165,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId)); | ||||
|             } | ||||
|  | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor)) | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId).GetFalseAwaitResult() is DmtpActor actor) | ||||
|             { | ||||
|                 return actor.CreateChannel(metadata); | ||||
|             } | ||||
| @@ -1100,37 +1188,37 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual Task<IDmtpChannel> CreateChannelAsync(string targetId, int id, Metadata metadata = default) | ||||
|         public virtual async Task<IDmtpChannel> CreateChannelAsync(string targetId, int id, Metadata metadata = default) | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(targetId)) | ||||
|             { | ||||
|                 throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId)); | ||||
|             } | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor)) | ||||
|             if (this.AllowRoute && await this.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|             { | ||||
|                 return actor.CreateChannelAsync(id, metadata); | ||||
|                 return await actor.CreateChannelAsync(id, metadata).ConfigureFalseAwait(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return this.PrivateCreateChannelAsync(targetId, false, id, metadata); | ||||
|                 return await this.PrivateCreateChannelAsync(targetId, false, id, metadata).ConfigureFalseAwait(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual Task<IDmtpChannel> CreateChannelAsync(string targetId, Metadata metadata = default) | ||||
|         public virtual async Task<IDmtpChannel> CreateChannelAsync(string targetId, Metadata metadata = default) | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(targetId)) | ||||
|             { | ||||
|                 throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId)); | ||||
|             } | ||||
|  | ||||
|             if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor)) | ||||
|             if (this.AllowRoute && await this.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|             { | ||||
|                 return actor.CreateChannelAsync(metadata); | ||||
|                 return await actor.CreateChannelAsync(metadata).ConfigureFalseAwait(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return this.PrivateCreateChannelAsync(targetId, true, 0, metadata); | ||||
|                 return await this.PrivateCreateChannelAsync(targetId, true, 0, metadata).ConfigureFalseAwait(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -1208,9 +1296,14 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                                         var channel = new InternalChannel(this, targetId, result.Metadata); | ||||
|                                         channel.SetId(result.ChannelId); | ||||
|                                         channel.SetUsing(); | ||||
|                                         return this.m_userChannels.TryAdd(result.ChannelId, channel) | ||||
|                                             ? (IDmtpChannel)channel | ||||
|                                             : throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription()); | ||||
|                                         if (this.m_userChannels.TryAdd(result.ChannelId, channel)) | ||||
|                                         { | ||||
|                                             return channel; | ||||
|                                         } | ||||
|                                         else | ||||
|                                         { | ||||
|                                             throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription()); | ||||
|                                         } | ||||
|                                     } | ||||
|                                 case TouchSocketDmtpStatus.ClientNotFind: | ||||
|                                     { | ||||
| @@ -1269,8 +1362,8 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             try | ||||
|             { | ||||
|                 waitCreateChannel.Package(byteBlock); | ||||
|                 this.Send(P7_CreateChannel_Request, byteBlock); | ||||
|                 switch (await waitData.WaitAsync(10 * 1000)) | ||||
|                 await this.SendAsync(P7_CreateChannel_Request, byteBlock).ConfigureFalseAwait(); | ||||
|                 switch (await waitData.WaitAsync(10 * 1000).ConfigureFalseAwait()) | ||||
|                 { | ||||
|                     case WaitDataStatus.SetRunning: | ||||
|                         { | ||||
| @@ -1282,9 +1375,14 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                                         var channel = new InternalChannel(this, targetId, result.Metadata); | ||||
|                                         channel.SetId(result.ChannelId); | ||||
|                                         channel.SetUsing(); | ||||
|                                         return this.m_userChannels.TryAdd(result.ChannelId, channel) | ||||
|                                             ? (IDmtpChannel)channel | ||||
|                                             : throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription()); | ||||
|                                         if (this.m_userChannels.TryAdd(result.ChannelId, channel)) | ||||
|                                         { | ||||
|                                             return channel; | ||||
|                                         } | ||||
|                                         else | ||||
|                                         { | ||||
|                                             throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription()); | ||||
|                                         } | ||||
|                                     } | ||||
|                                 case TouchSocketDmtpStatus.ClientNotFind: | ||||
|                                     { | ||||
| @@ -1333,7 +1431,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 channel.SetId(id); | ||||
|                 if (this.m_userChannels.TryAdd(id, channel)) | ||||
|                 { | ||||
|                     Task.Factory.StartNew(this.ThisRequestCreateChannel, new CreateChannelEventArgs(id, metadata)); | ||||
|                     Task.Factory.StartNew(this.PrivateOnCreatedChannel, new CreateChannelEventArgs(id, metadata)); | ||||
|                     return true; | ||||
|                 } | ||||
|                 else | ||||
| @@ -1344,16 +1442,6 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void ThisRequestCreateChannel(object state) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 this.OnCreateChannel?.Invoke(this, (CreateChannelEventArgs)state); | ||||
|             } | ||||
|             catch | ||||
|             { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #endregion IDmtpChannel | ||||
|     } | ||||
|   | ||||
| @@ -152,9 +152,8 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <summary> | ||||
|         /// 关闭 | ||||
|         /// </summary> | ||||
|         /// <param name="sendClose">是否发送close报文</param> | ||||
|         /// <param name="message">传递消息</param> | ||||
|         void Close(bool sendClose, string message); | ||||
|         void Close(string message); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 向当前对点发送一个Ping报文,并且等待回应。 | ||||
| @@ -226,6 +225,14 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <param name="length"></param> | ||||
|         Task SendAsync(ushort protocol, byte[] buffer, int offset, int length); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 异步发送字节块 | ||||
|         /// </summary> | ||||
|         /// <param name="protocol"></param> | ||||
|         /// <param name="byteBlock"></param> | ||||
|         /// <returns></returns> | ||||
|         Task SendAsync(ushort protocol, ByteBlock byteBlock); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 以Fast序列化,发送小(64K)对象。接收方需要使用ReadObject读取对象。 | ||||
|         /// </summary> | ||||
| @@ -260,25 +267,20 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// 尝试获取指定Id的DmtpActor。一般此方法仅在Service下有效。 | ||||
|         /// </summary> | ||||
|         /// <param name="targetId"></param> | ||||
|         /// <param name="actor"></param> | ||||
|         /// <returns></returns> | ||||
|         bool TryFindDmtpActor(string targetId, out DmtpActor actor); | ||||
|         Task<DmtpActor> TryFindDmtpActor(string targetId); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 尝试请求路由,触发路由相关插件。 | ||||
|         /// 尝试请求路由,触发路由相关插件。并在路由失败时向<see cref="MsgPermitEventArgs.Message"/>中传递消息。 | ||||
|         /// </summary> | ||||
|         /// <param name="routerType"></param> | ||||
|         /// <param name="routerPackage"></param> | ||||
|         /// <returns></returns> | ||||
|         bool TryRoute(RouteType routerType, RouterPackage routerPackage); | ||||
|         Task<bool> TryRoute(PackageRouterEventArgs e); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 尝试请求路由,触发路由相关插件。并在路由失败时向<see cref="MsgRouterPackage.Message"/>中传递消息。 | ||||
|         /// 发送Close请求 | ||||
|         /// </summary> | ||||
|         /// <param name="routerType"></param> | ||||
|         /// <param name="routerPackage"></param> | ||||
|         /// <returns></returns> | ||||
|         bool TryRoute(RouteType routerType, WaitRouterPackage routerPackage); | ||||
|         /// <param name="msg"></param> | ||||
|         bool SendClose(string msg); | ||||
|  | ||||
|         #endregion 方法 | ||||
|     } | ||||
|   | ||||
| @@ -17,17 +17,22 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|     /// </summary> | ||||
|     public class TcpDmtpAdapter : CustomFixedHeaderByteBlockDataHandlingAdapter<DmtpMessage> | ||||
|     { | ||||
|         private SpinLock m_locker = new SpinLock(); | ||||
|         private readonly SemaphoreSlim m_locker = new SemaphoreSlim(1, 1); | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override bool CanSendRequestInfo => true; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override bool CanSplicingSend => false; | ||||
|         public override bool CanSplicingSend => true; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int HeaderLength => 6; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 最大拼接 | ||||
|         /// </summary> | ||||
|         public const int MaxSplicing = 1024 * 64; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override DmtpMessage GetInstance() | ||||
|         { | ||||
| @@ -40,6 +45,25 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             request.SafeDispose(); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task PreviewSendAsync(IRequestInfo requestInfo) | ||||
|         { | ||||
|             if (!(requestInfo is DmtpMessage message)) | ||||
|             { | ||||
|                 throw new Exception($"无法将{nameof(requestInfo)}转换为{nameof(DmtpMessage)}"); | ||||
|             } | ||||
|             if (message.BodyByteBlock != null && message.BodyByteBlock.Length > this.MaxPackageSize) | ||||
|             { | ||||
|                 throw new Exception("发送的BodyLength={requestInfo.BodyLength},大于设定的MaxPackageSize={this.MaxPackageSize}"); | ||||
|             } | ||||
|             using (var byteBlock = new ByteBlock(message.GetLength())) | ||||
|             { | ||||
|                 message.Build(byteBlock); | ||||
|                 await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override void PreviewSend(IRequestInfo requestInfo) | ||||
|         { | ||||
| @@ -58,6 +82,54 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes) | ||||
|         { | ||||
|             if (transferBytes.Count == 0) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             var length = 0; | ||||
|             foreach (var item in transferBytes) | ||||
|             { | ||||
|                 length += item.Count; | ||||
|             } | ||||
|  | ||||
|             if (length > this.MaxPackageSize) | ||||
|             { | ||||
|                 throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送"); | ||||
|             } | ||||
|             if (length > this.MaxPackageSize) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|  | ||||
|                     await this.m_locker.WaitAsync(); | ||||
|                     foreach (var item in transferBytes) | ||||
|                     { | ||||
|                         await this.GoSendAsync(item.Array, item.Offset, item.Count); | ||||
|                     } | ||||
|                 } | ||||
|                 finally | ||||
|                 { | ||||
|                     this.m_locker.Release(); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 using (var byteBlock = new ByteBlock(length)) | ||||
|                 { | ||||
|                     foreach (var item in transferBytes) | ||||
|                     { | ||||
|                         byteBlock.Write(item.Array, item.Offset, item.Count); | ||||
|                     } | ||||
|                     await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override void PreviewSend(IList<ArraySegment<byte>> transferBytes) | ||||
|         { | ||||
| @@ -77,20 +149,31 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送"); | ||||
|             } | ||||
|  | ||||
|             var lockTaken = false; | ||||
|             try | ||||
|             if (length > this.MaxPackageSize) | ||||
|             { | ||||
|                 this.m_locker.Enter(ref lockTaken); | ||||
|                 foreach (var item in transferBytes) | ||||
|                 try | ||||
|                 { | ||||
|                     this.GoSend(item.Array, item.Offset, item.Count); | ||||
|  | ||||
|                     this.m_locker.Wait(); | ||||
|                     foreach (var item in transferBytes) | ||||
|                     { | ||||
|                         this.GoSend(item.Array, item.Offset, item.Count); | ||||
|                     } | ||||
|                 } | ||||
|                 finally | ||||
|                 { | ||||
|                     this.m_locker.Release(); | ||||
|                 } | ||||
|             } | ||||
|             finally | ||||
|             else | ||||
|             { | ||||
|                 if (lockTaken) | ||||
|                 using (var byteBlock = new ByteBlock(length)) | ||||
|                 { | ||||
|                     this.m_locker.Exit(false); | ||||
|                     foreach (var item in transferBytes) | ||||
|                     { | ||||
|                         byteBlock.Write(item.Array, item.Offset, item.Count); | ||||
|                     } | ||||
|                     this.GoSend(byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -70,7 +70,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <summary> | ||||
|         /// 最大传输速度。 | ||||
|         /// </summary> | ||||
|         public long MaxSpeed { get => this.m_flowGate.Maximum; set => this.m_flowGate.Maximum = value; } | ||||
|         public virtual long MaxSpeed { get => this.m_flowGate.Maximum; set => this.m_flowGate.Maximum = value; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 元数据 | ||||
|   | ||||
| @@ -33,19 +33,19 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         #region 字段 | ||||
|  | ||||
|         private bool m_allowRoute; | ||||
|         private Func<string, IDmtpActor> m_findDmtpActor; | ||||
|         private DmtpActor m_smtpActor; | ||||
|         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||
|         private DmtpActor m_dmtpActor; | ||||
|         private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); | ||||
|         #endregion 字段 | ||||
|  | ||||
|         /// <inheritdoc cref="IDmtpActor.Id"/> | ||||
|         public string Id => this.DmtpActor.Id; | ||||
|         public string Id => this.m_dmtpActor.Id; | ||||
|  | ||||
|         /// <inheritdoc cref="IDmtpActor.IsHandshaked"/> | ||||
|         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; | ||||
|         public bool IsHandshaked => this.m_dmtpActor != null && this.m_dmtpActor.IsHandshaked; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IDmtpActor DmtpActor { get => this.m_smtpActor; } | ||||
|         public IDmtpActor DmtpActor { get => this.m_dmtpActor; } | ||||
|  | ||||
|         #region 连接 | ||||
|  | ||||
| @@ -78,7 +78,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 if (response.StatusCode == 101) | ||||
|                 { | ||||
|                     this.SwitchProtocolToDmtp(); | ||||
|                     this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                     this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                         this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), | ||||
|                         timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); | ||||
|                     return this; | ||||
| @@ -114,7 +114,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 if (response.StatusCode == 101) | ||||
|                 { | ||||
|                     this.SwitchProtocolToDmtp(); | ||||
|                     this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                     this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                         this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), | ||||
|                         timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); | ||||
|                     return this; | ||||
| @@ -156,7 +156,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 if (response.StatusCode == 101) | ||||
|                 { | ||||
|                     this.SwitchProtocolToDmtp(); | ||||
|                     await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                     await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                          this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), | ||||
|                          timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); | ||||
|                     return this; | ||||
| @@ -184,7 +184,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 } | ||||
|                 if (!this.Online) | ||||
|                 { | ||||
|                     await base.ConnectAsync(timeout, token); | ||||
|                     await base.ConnectAsync(timeout); | ||||
|                 } | ||||
|  | ||||
|                 var request = new HttpRequest() | ||||
| @@ -197,7 +197,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 if (response.StatusCode == 101) | ||||
|                 { | ||||
|                     this.SwitchProtocolToDmtp(); | ||||
|                     await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                     await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                          this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), | ||||
|                          timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); | ||||
|                     return this; | ||||
| @@ -215,19 +215,47 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|         #endregion 连接 | ||||
|  | ||||
|         #region 断开 | ||||
|         /// <inheritdoc/> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             this.DmtpActor.SafeDispose(); | ||||
|             if (this.IsHandshaked) | ||||
|             { | ||||
|                 this.m_dmtpActor?.SafeDispose(); | ||||
|             } | ||||
|             base.Dispose(disposing); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 发送<see cref="IDmtpActor"/>关闭消息。 | ||||
|         /// </summary> | ||||
|         /// <param name="msg"></param> | ||||
|         /// <returns></returns> | ||||
|         public override void Close(string msg = "") | ||||
|         { | ||||
|             if (this.IsHandshaked) | ||||
|             { | ||||
|                 this.m_dmtpActor.SendClose(msg); | ||||
|                 this.m_dmtpActor.Close(msg); | ||||
|             } | ||||
|             base.Close(msg); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||
|         { | ||||
|             this.m_dmtpActor?.Close(e.Message); | ||||
|             await base.OnDisconnected(e); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||
|         { | ||||
|             if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message) | ||||
|             { | ||||
|                 if (!this.m_smtpActor.InputReceivedData(message)) | ||||
|                 if (!await this.m_dmtpActor.InputReceivedData(message)) | ||||
|                 { | ||||
|                     if (this.PluginsManager.Enable) | ||||
|                     { | ||||
| @@ -250,25 +278,19 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||
|         { | ||||
|             await base.OnDisconnected(e); | ||||
|             this.DmtpActor.Close(false, e.Message); | ||||
|         } | ||||
|  | ||||
|         #region ResetId | ||||
|  | ||||
|         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> | ||||
|         public void ResetId(string id) | ||||
|         { | ||||
|             this.m_smtpActor.ResetId(id); | ||||
|             this.m_dmtpActor.ResetId(id); | ||||
|         } | ||||
|  | ||||
|         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> | ||||
|         public Task ResetIdAsync(string newId) | ||||
|         { | ||||
|             return this.m_smtpActor.ResetIdAsync(newId); | ||||
|             return this.m_dmtpActor.ResetIdAsync(newId); | ||||
|         } | ||||
|  | ||||
|         #endregion ResetId | ||||
| @@ -277,72 +299,47 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         { | ||||
|             this.Protocol = DmtpUtility.DmtpProtocol; | ||||
|             this.SetDataHandlingAdapter(new TcpDmtpAdapter()); | ||||
|             this.m_smtpActor = new SealedDmtpActor(this.m_allowRoute) | ||||
|             this.m_dmtpActor = new SealedDmtpActor(this.m_allowRoute) | ||||
|             { | ||||
|                 OutputSend = DmtpActorSend, | ||||
|                 OnRouting = OnDmtpActorRouting, | ||||
|                 OnHandshaking = this.OnDmtpActorHandshaking, | ||||
|                 OnHandshaked = OnDmtpActorHandshaked, | ||||
|                 OnClose = OnDmtpActorClose, | ||||
|                 OnCreateChannel = this.OnDmtpActorCreateChannel, | ||||
|                 OutputSend = this.DmtpActorSend, | ||||
|                 OutputSendAsync = this.DmtpActorSendAsync, | ||||
|                 Routing = this.OnDmtpActorRouting, | ||||
|                 Handshaking = this.OnDmtpActorHandshaking, | ||||
|                 Handshaked = this.OnDmtpActorHandshaked, | ||||
|                 Closed = this.OnDmtpActorClose, | ||||
|                 CreatedChannel = this.OnDmtpActorCreateChannel, | ||||
|                 Logger = this.Logger, | ||||
|                 Client = this, | ||||
|                 OnFindDmtpActor = this.m_findDmtpActor | ||||
|                 FindDmtpActor = this.m_findDmtpActor | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         #region 内部委托绑定 | ||||
|  | ||||
|         private void OnDmtpActorClose(DmtpActor actor, string msg) | ||||
|         private Task OnDmtpActorClose(DmtpActor actor, string msg) | ||||
|         { | ||||
|             base.Close(msg); | ||||
|             base.BreakOut(false, msg); | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         { | ||||
|             this.OnCreateChannel(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|             return this.OnCreateChannel(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             this.OnHandshaked(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             return this.OnHandshaked(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             this.OnHandshaking(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); | ||||
|             return this.OnHandshaking(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         { | ||||
|             this.OnRouting(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             return this.OnRouting(e); | ||||
|         } | ||||
|  | ||||
|         private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
| @@ -350,6 +347,11 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             base.Send(transferBytes); | ||||
|         } | ||||
|  | ||||
|         private Task DmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             return base.SendAsync(transferBytes); | ||||
|         } | ||||
|  | ||||
|         #endregion 内部委托绑定 | ||||
|  | ||||
|         #region 事件触发 | ||||
| @@ -358,32 +360,53 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// 当创建通道 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnCreateChannel(CreateChannelEventArgs e) | ||||
|         protected virtual async Task OnCreateChannel(CreateChannelEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在完成握手连接时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 即将握手连接时 | ||||
|         /// </summary> | ||||
|         /// <param name="e">参数</param> | ||||
|         protected virtual void OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当需要转发路由包时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnRouting(PackageRouterEventArgs e) | ||||
|         protected virtual async Task OnRouting(PackageRouterEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e); | ||||
|         } | ||||
|  | ||||
|         #endregion 事件触发 | ||||
|   | ||||
| @@ -46,7 +46,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         #region 字段 | ||||
|  | ||||
|         private bool m_allowRoute; | ||||
|         private Func<string, IDmtpActor> m_findDmtpActor; | ||||
|         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||
|  | ||||
|         #endregion 字段 | ||||
|  | ||||
| @@ -68,17 +68,28 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             await base.OnConnected(socketClient, e); | ||||
|         } | ||||
|  | ||||
|         private IDmtpActor OnServiceFindDmtpActor(string id) | ||||
|         { | ||||
|             return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null; | ||||
|         } | ||||
|  | ||||
|         private DmtpActor PrivateOnRpcActorInit() | ||||
|         { | ||||
|             return new SealedDmtpActor(this.m_allowRoute) | ||||
|             { | ||||
|                 OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null | ||||
|                 FindDmtpActor = this.FindDmtpActor | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         private async Task<IDmtpActor> FindDmtpActor(string id) | ||||
|         { | ||||
|             if (this.m_allowRoute) | ||||
|             { | ||||
|                 if (this.m_findDmtpActor != null) | ||||
|                 { | ||||
|                     return await this.m_findDmtpActor.Invoke(id); | ||||
|                 } | ||||
|                 return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -31,14 +31,14 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|     public class HttpDmtpSocketClient : HttpSocketClient, IHttpDmtpSocketClient | ||||
|     { | ||||
|         internal Func<DmtpActor> m_internalOnRpcActorInit; | ||||
|         private DmtpActor m_smtpActor; | ||||
|         private DmtpActor m_dmtpActor; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IDmtpActor DmtpActor { get => this.m_dmtpActor; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IDmtpActor DmtpActor { get => this.m_smtpActor; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 验证超时时间,默认为3000ms | ||||
|         /// </summary> | ||||
| @@ -49,97 +49,67 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// </summary> | ||||
|         public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty); | ||||
|  | ||||
|         #region 断开 | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override void Close(string msg = "") | ||||
|         { | ||||
|             if (this.m_smtpActor == null) | ||||
|             if (this.m_dmtpActor != null) | ||||
|             { | ||||
|                 base.Close(msg); | ||||
|                 return; | ||||
|                 this.m_dmtpActor.SendClose(msg); | ||||
|                 this.m_dmtpActor.Close(msg); | ||||
|             } | ||||
|             this.m_smtpActor.Close(true, msg); | ||||
|             base.Close(msg); | ||||
|         } | ||||
|  | ||||
|         #region ResetId | ||||
|  | ||||
|         /// <inheritdoc cref="IDmtpActor.ResetId(string)"/> | ||||
|         public override void ResetId(string newId) | ||||
|         { | ||||
|             if (this.m_smtpActor == null) | ||||
|             { | ||||
|                 base.ResetId(newId); | ||||
|                 return; | ||||
|             } | ||||
|             this.m_smtpActor.ResetId(newId); | ||||
|         } | ||||
|  | ||||
|         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> | ||||
|         public async Task ResetIdAsync(string newId) | ||||
|         { | ||||
|             if (this.m_smtpActor == null) | ||||
|             { | ||||
|                 base.ResetId(newId); | ||||
|                 return; | ||||
|             } | ||||
|             await this.m_smtpActor.ResetIdAsync(newId); | ||||
|         } | ||||
|  | ||||
|         #endregion ResetId | ||||
|  | ||||
|         /// <summary> | ||||
|         /// <inheritdoc/> | ||||
|         /// </summary> | ||||
|         /// <param name="disposing"></param> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             this.DmtpActor?.SafeDispose(); | ||||
|             this.m_dmtpActor?.SafeDispose(); | ||||
|             base.Dispose(disposing); | ||||
|         } | ||||
|  | ||||
|         ///// <inheritdoc/> | ||||
|         //protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) | ||||
|         //{ | ||||
|         //    if (this.Protocol == DmtpUtility.DmtpProtocol && requestInfo is DmtpMessage message) | ||||
|         //    { | ||||
|         //        if (!this.m_smtpActor.InputReceivedData(message)) | ||||
|         //        { | ||||
|         //            if (this.PluginsManager.Enable) | ||||
|         //            { | ||||
|         //                this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); | ||||
|         //            } | ||||
|         //        } | ||||
|  | ||||
|         //        return false; | ||||
|         //    } | ||||
|         //    else | ||||
|         //    { | ||||
|         //        return base.HandleReceivedData(byteBlock, requestInfo); | ||||
|         //    } | ||||
|         //} | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||
|         { | ||||
|             if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message) | ||||
|             { | ||||
|                 if (!this.m_smtpActor.InputReceivedData(message)) | ||||
|                 { | ||||
|                     await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); | ||||
|                 } | ||||
|             } | ||||
|             await base.ReceivedData(e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// <inheritdoc/> | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||
|         { | ||||
|             this.DmtpActor?.Close(false, e.Message); | ||||
|             this.m_dmtpActor?.Close(e.Message); | ||||
|             await base.OnDisconnected(e); | ||||
|         } | ||||
|  | ||||
|         #endregion 断开 | ||||
|  | ||||
|         #region ResetId | ||||
|  | ||||
|         /// <inheritdoc cref="IDmtpActor.ResetId(string)"/> | ||||
|         public override void ResetId(string newId) | ||||
|         { | ||||
|             if (this.m_dmtpActor == null) | ||||
|             { | ||||
|                 base.ResetId(newId); | ||||
|                 return; | ||||
|             } | ||||
|             this.m_dmtpActor.ResetId(newId); | ||||
|         } | ||||
|  | ||||
|         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> | ||||
|         public async Task ResetIdAsync(string newId) | ||||
|         { | ||||
|             if (this.m_dmtpActor == null) | ||||
|             { | ||||
|                 base.ResetId(newId); | ||||
|                 return; | ||||
|             } | ||||
|             await this.m_dmtpActor.ResetIdAsync(newId); | ||||
|         } | ||||
|  | ||||
|         #endregion ResetId | ||||
|  | ||||
|         /// <summary> | ||||
|         /// <inheritdoc/> | ||||
|         /// </summary> | ||||
| @@ -158,66 +128,73 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             await base.OnReceivedHttpRequest(request); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||
|         { | ||||
|             if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message) | ||||
|             { | ||||
|                 if (!await this.m_dmtpActor.InputReceivedData(message)) | ||||
|                 { | ||||
|                     await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); | ||||
|                 } | ||||
|             } | ||||
|             await base.ReceivedData(e); | ||||
|         } | ||||
|  | ||||
|         private Task OnDmtpIdChanged(DmtpActor actor, IdChangedEventArgs e) | ||||
|         { | ||||
|             this.DirectResetId(e.NewId); | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private void SetRpcActor(DmtpActor actor) | ||||
|         { | ||||
|             actor.Id = this.Id; | ||||
|             actor.OnResetId = this.ThisOnResetId; | ||||
|             actor.IdChanged = this.OnDmtpIdChanged; | ||||
|             actor.OutputSendAsync = this.ThisDmtpActorOutputSendAsync; | ||||
|             actor.OutputSend = this.ThisDmtpActorOutputSend; | ||||
|             actor.Client = this; | ||||
|             actor.OnClose = this.OnDmtpActorClose; | ||||
|             actor.OnRouting = this.OnDmtpActorRouting; | ||||
|             actor.OnHandshaked = this.OnDmtpActorHandshaked; | ||||
|             actor.OnHandshaking = this.OnDmtpActorHandshaking; | ||||
|             actor.OnCreateChannel = this.OnDmtpActorCreateChannel; | ||||
|             actor.Closed = this.OnDmtpActorClose; | ||||
|             actor.Routing = this.OnDmtpActorRouting; | ||||
|             actor.Handshaked = this.OnDmtpActorHandshaked; | ||||
|             actor.Handshaking = this.OnDmtpActorHandshaking; | ||||
|             actor.CreatedChannel = this.OnDmtpActorCreatedChannel; | ||||
|             actor.Logger = this.Logger; | ||||
|             this.m_smtpActor = actor; | ||||
|             this.m_dmtpActor = actor; | ||||
|  | ||||
|             this.Protocol = DmtpUtility.DmtpProtocol; | ||||
|             this.SetDataHandlingAdapter(new TcpDmtpAdapter()); | ||||
|         } | ||||
|  | ||||
|         private void ThisOnResetId(DmtpActor actor, WaitSetId waitSetId) | ||||
|         { | ||||
|             this.DirectResetId(waitSetId.NewId); | ||||
|         } | ||||
|  | ||||
|         private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             base.Send(transferBytes); | ||||
|         } | ||||
|  | ||||
|         private Task ThisDmtpActorOutputSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             return base.SendAsync(transferBytes); | ||||
|         } | ||||
|  | ||||
|         #region 内部委托绑定 | ||||
|  | ||||
|         private void OnDmtpActorClose(DmtpActor actor, string msg) | ||||
|         private Task OnDmtpActorClose(DmtpActor actor, string msg) | ||||
|         { | ||||
|             base.Close(msg); | ||||
|             base.BreakOut(false, msg); | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         private Task OnDmtpActorCreatedChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         { | ||||
|             this.OnCreateChannel(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|             return this.OnCreatedChannel(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             this.OnHandshaked(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             return this.OnHandshaked(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Token == this.VerifyToken) | ||||
|             { | ||||
| @@ -228,25 +205,12 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 e.Message = "Token不受理"; | ||||
|             } | ||||
|  | ||||
|             this.OnHandshaking(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); | ||||
|             return this.OnHandshaking(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         { | ||||
|             this.OnRouting(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             return this.OnRouting(e); | ||||
|         } | ||||
|  | ||||
|         #endregion 内部委托绑定 | ||||
| @@ -257,32 +221,53 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// 当创建通道 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnCreateChannel(CreateChannelEventArgs e) | ||||
|         protected virtual async Task OnCreatedChannel(CreateChannelEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在完成握手连接时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在验证Token时 | ||||
|         /// </summary> | ||||
|         /// <param name="e">参数</param> | ||||
|         protected virtual void OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在需要转发路由包时。 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnRouting(PackageRouterEventArgs e) | ||||
|         protected virtual async Task OnRouting(PackageRouterEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e); | ||||
|         } | ||||
|  | ||||
|         #endregion 事件 | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Dmtp | ||||
| { | ||||
|     /// <summary> | ||||
|   | ||||
| @@ -39,22 +39,24 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IDmtpActor DmtpActor { get => this.m_smtpActor; } | ||||
|         public IDmtpActor DmtpActor { get => this.m_dmtpActor; } | ||||
|  | ||||
|         /// <inheritdoc cref="IDmtpActor.Id"/> | ||||
|         public string Id => this.DmtpActor.Id; | ||||
|         public string Id => this.m_dmtpActor.Id; | ||||
|  | ||||
|         #region 字段 | ||||
|  | ||||
|         private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); | ||||
|         private bool m_allowRoute; | ||||
|         private Func<string, IDmtpActor> m_findDmtpActor; | ||||
|         private SealedDmtpActor m_smtpActor; | ||||
|         private SealedDmtpActor m_dmtpActor; | ||||
|         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||
|  | ||||
|         #endregion 字段 | ||||
|  | ||||
|         /// <inheritdoc cref="IDmtpActor.IsHandshaked"/> | ||||
|         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; | ||||
|         public bool IsHandshaked => this.m_dmtpActor != null && this.m_dmtpActor.IsHandshaked; | ||||
|  | ||||
|         #region 断开 | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 发送<see cref="IDmtpActor"/>关闭消息。 | ||||
| @@ -63,10 +65,33 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <returns></returns> | ||||
|         public override void Close(string msg = "") | ||||
|         { | ||||
|             this.DmtpActor.Close(true, msg); | ||||
|             if (this.IsHandshaked) | ||||
|             { | ||||
|                 this.m_dmtpActor?.SendClose(msg); | ||||
|                 this.m_dmtpActor?.Close(msg); | ||||
|             } | ||||
|             base.Close(msg); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             if (this.IsHandshaked) | ||||
|             { | ||||
|                 this.m_dmtpActor?.SafeDispose(); | ||||
|             } | ||||
|             base.Dispose(disposing); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||
|         { | ||||
|             this.m_dmtpActor?.Close(e.Message); | ||||
|             await base.OnDisconnected(e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         #endregion 断开 | ||||
|  | ||||
|         #region 连接 | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -87,7 +112,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                     base.Connect(timeout); | ||||
|                 } | ||||
|  | ||||
|                 this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                 this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                     this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); | ||||
|                 return this; | ||||
|             } | ||||
| @@ -107,7 +132,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                     base.Connect(timeout); | ||||
|                 } | ||||
|  | ||||
|                 this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                 this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                     this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); | ||||
|                 return this; | ||||
|             } | ||||
| @@ -129,11 +154,10 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 } | ||||
|                 if (!this.Online) | ||||
|                 { | ||||
|                     await base.ConnectAsync(timeout); | ||||
|                     await base.ConnectAsync(timeout).ConfigureFalseAwait(); | ||||
|                 } | ||||
|  | ||||
|                 await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                      this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); | ||||
|                 await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None).ConfigureFalseAwait(); | ||||
|                 return this; | ||||
|             } | ||||
|             finally | ||||
| @@ -154,11 +178,10 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 } | ||||
|                 if (!this.Online) | ||||
|                 { | ||||
|                     await base.ConnectAsync(timeout, token); | ||||
|                     await base.ConnectAsync(timeout).ConfigureFalseAwait(); | ||||
|                 } | ||||
|  | ||||
|                 await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                      this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); | ||||
|                 await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token).ConfigureFalseAwait(); | ||||
|                 return this; | ||||
|             } | ||||
|             finally | ||||
| @@ -174,13 +197,13 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> | ||||
|         public void ResetId(string id) | ||||
|         { | ||||
|             this.m_smtpActor.ResetId(id); | ||||
|             this.m_dmtpActor.ResetId(id); | ||||
|         } | ||||
|  | ||||
|         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> | ||||
|         public Task ResetIdAsync(string newId) | ||||
|         { | ||||
|             return this.m_smtpActor.ResetIdAsync(newId); | ||||
|             return this.m_dmtpActor.ResetIdAsync(newId); | ||||
|         } | ||||
|  | ||||
|         #endregion ResetId | ||||
| @@ -229,13 +252,6 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|         #endregion 发送 | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             this.DmtpActor.SafeDispose(); | ||||
|             base.Dispose(disposing); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override void LoadConfig(TouchSocketConfig config) | ||||
|         { | ||||
| @@ -246,37 +262,31 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 this.m_allowRoute = true; | ||||
|                 this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor; | ||||
|             } | ||||
|             this.m_smtpActor = new SealedDmtpActor(this.m_allowRoute) | ||||
|             this.m_dmtpActor = new SealedDmtpActor(this.m_allowRoute) | ||||
|             { | ||||
|                 OutputSend = this.DmtpActorSend, | ||||
|                 OnRouting = this.OnDmtpActorRouting, | ||||
|                 OnHandshaking = this.OnDmtpActorHandshaking, | ||||
|                 OnHandshaked = this.OnDmtpActorHandshaked, | ||||
|                 OnClose = this.OnDmtpActorClose, | ||||
|                 OutputSendAsync = this.DmtpActorSendAsync, | ||||
|                 Routing = this.OnDmtpActorRouting, | ||||
|                 Handshaking = this.OnDmtpActorHandshaking, | ||||
|                 Handshaked = this.OnDmtpActorHandshaked, | ||||
|                 Closed = this.OnDmtpActorClose, | ||||
|                 Logger = this.Logger, | ||||
|                 Client = this, | ||||
|                 OnFindDmtpActor = this.m_findDmtpActor, | ||||
|                 OnCreateChannel = this.OnDmtpActorCreateChannel | ||||
|                 FindDmtpActor = this.m_findDmtpActor, | ||||
|                 CreatedChannel = this.OnDmtpActorCreateChannel | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||
|         { | ||||
|             await base.OnDisconnected(e); | ||||
|             this.DmtpActor.Close(false, e.Message); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||
|         { | ||||
|             var message = (DmtpMessage)e.RequestInfo; | ||||
|             if (!this.m_smtpActor.InputReceivedData(message)) | ||||
|             if (!await this.m_dmtpActor.InputReceivedData(message).ConfigureFalseAwait()) | ||||
|             { | ||||
|                 await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); | ||||
|                 await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)).ConfigureFalseAwait(); | ||||
|             } | ||||
|  | ||||
|             await base.ReceivedData(e); | ||||
|             await base.ReceivedData(e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         #region 内部委托绑定 | ||||
| @@ -286,52 +296,35 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             base.Send(transferBytes); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorClose(DmtpActor actor, string msg) | ||||
|         private Task DmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             base.Close(msg); | ||||
|             return base.SendAsync(transferBytes); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         private Task OnDmtpActorClose(DmtpActor actor, string msg) | ||||
|         { | ||||
|             this.OnCreateChannel(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|             this.BreakOut(false, msg); | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         { | ||||
|             this.OnHandshaked(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             return this.OnCreatedChannel(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             this.OnHandshaking(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); | ||||
|             return this.OnHandshaked(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             this.OnRouting(e); | ||||
|             return this.OnHandshaking(e); | ||||
|         } | ||||
|  | ||||
|         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         { | ||||
|             return this.OnRouting(e); | ||||
|         } | ||||
|  | ||||
|         #endregion 内部委托绑定 | ||||
| @@ -342,32 +335,53 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// 当创建通道 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnCreateChannel(CreateChannelEventArgs e) | ||||
|         protected virtual async Task OnCreatedChannel(CreateChannelEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在完成握手连接时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 即将握手连接时 | ||||
|         /// </summary> | ||||
|         /// <param name="e">参数</param> | ||||
|         protected virtual void OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当需要转发路由包时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnRouting(PackageRouterEventArgs e) | ||||
|         protected virtual async Task OnRouting(PackageRouterEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         #endregion 事件触发 | ||||
|   | ||||
| @@ -41,7 +41,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         #region 字段 | ||||
|  | ||||
|         private bool m_allowRoute; | ||||
|         private Func<string, IDmtpActor> m_findDmtpActor; | ||||
|         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||
|  | ||||
|         #endregion 字段 | ||||
|  | ||||
| @@ -73,14 +73,25 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             socketClient.SetDmtpActor(new SealedDmtpActor(this.m_allowRoute) | ||||
|             { | ||||
|                 Id = e.Id, | ||||
|                 OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null | ||||
|                 FindDmtpActor = this.FindDmtpActor | ||||
|             }); | ||||
|             await base.OnConnecting(socketClient, e); | ||||
|         } | ||||
|  | ||||
|         private IDmtpActor OnServiceFindDmtpActor(string id) | ||||
|         private async Task<IDmtpActor> FindDmtpActor(string id) | ||||
|         { | ||||
|             return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null; | ||||
|             if (this.m_allowRoute) | ||||
|             { | ||||
|                 if (this.m_findDmtpActor != null) | ||||
|                 { | ||||
|                     return await this.m_findDmtpActor.Invoke(id); | ||||
|                 } | ||||
|                 return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -30,7 +30,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|     /// </summary> | ||||
|     public partial class TcpDmtpSocketClient : SocketClient, ITcpDmtpSocketClient | ||||
|     { | ||||
|         private DmtpActor m_smtpActor; | ||||
|         private DmtpActor m_dmtpActor; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// TcpDmtpSocketClient | ||||
| @@ -41,7 +41,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IDmtpActor DmtpActor { get => this.m_smtpActor; } | ||||
|         public IDmtpActor DmtpActor { get => this.m_dmtpActor; } | ||||
|  | ||||
|         /// <inheritdoc cref="IDmtpActor.IsHandshaked"/> | ||||
|         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; | ||||
| @@ -58,36 +58,23 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|         #region 内部委托绑定 | ||||
|  | ||||
|         private void OnDmtpActorClose(DmtpActor actor, string msg) | ||||
|         private Task OnDmtpActorClose(DmtpActor actor, string msg) | ||||
|         { | ||||
|             base.Close(msg); | ||||
|             base.BreakOut(false, msg); | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         { | ||||
|             this.OnCreateChannel(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|             return this.OnCreateChannel(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             this.OnHandshaked(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             return this.OnHandshaked(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private async Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Token == this.VerifyToken) | ||||
|             { | ||||
| @@ -98,25 +85,12 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                 e.Message = "Token不受理"; | ||||
|             } | ||||
|  | ||||
|             this.OnHandshaking(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); | ||||
|             await this.OnHandshaking(e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         { | ||||
|             this.OnRouting(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             return this.OnRouting(e); | ||||
|         } | ||||
|  | ||||
|         #endregion 内部委托绑定 | ||||
| @@ -127,99 +101,147 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// 当创建通道 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnCreateChannel(CreateChannelEventArgs e) | ||||
|         protected virtual async Task OnCreateChannel(CreateChannelEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在完成握手连接时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在验证Token时 | ||||
|         /// </summary> | ||||
|         /// <param name="e">参数</param> | ||||
|         protected virtual void OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在需要转发路由包时。 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnRouting(PackageRouterEventArgs e) | ||||
|         protected virtual async Task OnRouting(PackageRouterEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e); | ||||
|         } | ||||
|  | ||||
|         #endregion 事件 | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         #region 断开 | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 发送<see cref="IDmtpActor"/>关闭消息。 | ||||
|         /// </summary> | ||||
|         /// <param name="msg"></param> | ||||
|         /// <returns></returns> | ||||
|         public override void Close(string msg = "") | ||||
|         { | ||||
|             this.m_smtpActor.Close(true, msg); | ||||
|             if (this.IsHandshaked) | ||||
|             { | ||||
|                 this.m_dmtpActor?.SendClose(msg); | ||||
|                 this.m_dmtpActor?.Close(msg); | ||||
|             } | ||||
|             base.Close(msg); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             if (this.IsHandshaked) | ||||
|             { | ||||
|                 this.m_dmtpActor?.SafeDispose(); | ||||
|             } | ||||
|             base.Dispose(disposing); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||
|         { | ||||
|             if (this.IsHandshaked) | ||||
|             { | ||||
|                 this.m_dmtpActor?.Close(e.Message); | ||||
|             } | ||||
|             await base.OnDisconnected(e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         #endregion 断开 | ||||
|  | ||||
|         #region ResetId | ||||
|  | ||||
|         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> | ||||
|         public override void ResetId(string id) | ||||
|         { | ||||
|             this.m_smtpActor.ResetId(id); | ||||
|             this.m_dmtpActor.ResetId(id); | ||||
|         } | ||||
|  | ||||
|         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> | ||||
|         public Task ResetIdAsync(string newId) | ||||
|         { | ||||
|             return this.m_smtpActor.ResetIdAsync(newId); | ||||
|             return this.m_dmtpActor.ResetIdAsync(newId); | ||||
|         } | ||||
|  | ||||
|         #endregion ResetId | ||||
|  | ||||
|         internal void SetDmtpActor(DmtpActor actor) | ||||
|         { | ||||
|             actor.OnResetId = this.ThisOnResetId; | ||||
|             actor.IdChanged = this.ThisOnResetId; | ||||
|             actor.OutputSend = this.ThisDmtpActorOutputSend; | ||||
|             actor.OutputSendAsync = this.ThisDmtpActorOutputSendAsync; | ||||
|             actor.Client = this; | ||||
|             actor.OnClose = this.OnDmtpActorClose; | ||||
|             actor.OnRouting = this.OnDmtpActorRouting; | ||||
|             actor.OnHandshaked = this.OnDmtpActorHandshaked; | ||||
|             actor.OnHandshaking = this.OnDmtpActorHandshaking; | ||||
|             actor.OnCreateChannel = this.OnDmtpActorCreateChannel; | ||||
|             actor.Closed = this.OnDmtpActorClose; | ||||
|             actor.Routing = this.OnDmtpActorRouting; | ||||
|             actor.Handshaked = this.OnDmtpActorHandshaked; | ||||
|             actor.Handshaking = this.OnDmtpActorHandshaking; | ||||
|             actor.CreatedChannel = this.OnDmtpActorCreateChannel; | ||||
|             actor.Logger = this.Logger; | ||||
|             this.m_smtpActor = actor; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             this.DmtpActor.SafeDispose(); | ||||
|             base.Dispose(disposing); | ||||
|             this.m_dmtpActor = actor; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||
|         { | ||||
|             var message = (DmtpMessage)e.RequestInfo; | ||||
|             if (!this.m_smtpActor.InputReceivedData(message)) | ||||
|             if (!await this.m_dmtpActor.InputReceivedData(message).ConfigureFalseAwait()) | ||||
|             { | ||||
|                 await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); | ||||
|                 await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)).ConfigureFalseAwait(); | ||||
|             } | ||||
|             await base.ReceivedData(e); | ||||
|             await base.ReceivedData(e).ConfigureFalseAwait(); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task OnConnected(ConnectedEventArgs e) | ||||
|         { | ||||
|             this.m_smtpActor.Id = this.Id; | ||||
|             await base.OnConnected(e); | ||||
|             this.m_dmtpActor.Id = this.Id; | ||||
|             await base.OnConnected(e).ConfigureFalseAwait(); | ||||
|  | ||||
|             _ = Task.Run(async () => | ||||
|             { | ||||
|                 await Task.Delay(this.VerifyTimeout); | ||||
|                 await Task.Delay(this.VerifyTimeout).ConfigureFalseAwait(); | ||||
|                 if (!this.IsHandshaked) | ||||
|                 { | ||||
|                     this.TryShutdown(); | ||||
| @@ -228,21 +250,20 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||
|         { | ||||
|             this.DmtpActor.Close(false, e.Message); | ||||
|             await base.OnDisconnected(e); | ||||
|         } | ||||
|  | ||||
|         private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             base.Send(transferBytes); | ||||
|         } | ||||
|  | ||||
|         private void ThisOnResetId(DmtpActor rpcActor, WaitSetId waitSetId) | ||||
|         private Task ThisDmtpActorOutputSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             this.DirectResetId(waitSetId.NewId); | ||||
|             return base.SendAsync(transferBytes); | ||||
|         } | ||||
|  | ||||
|         private Task ThisOnResetId(DmtpActor rpcActor, IdChangedEventArgs e) | ||||
|         { | ||||
|             this.DirectResetId(e.NewId); | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         #region 发送 | ||||
|   | ||||
| @@ -84,7 +84,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|             } | ||||
|  | ||||
|             var message = DmtpMessage.CreateFrom(e.ByteBlock); | ||||
|             if (!client.InputReceivedData(message)) | ||||
|             if (!await client.InputReceivedData(message)) | ||||
|             { | ||||
|                 if (this.PluginsManager.Enable) | ||||
|                 { | ||||
|   | ||||
| @@ -45,16 +45,17 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|         { | ||||
|             this.Id = endPoint.ToString(); | ||||
|             this.OutputSend = this.RpcActorSend; | ||||
|             this.OnCreateChannel = this.OnDmtpActorCreateChannel; | ||||
|             this.OutputSendAsync = this.RpcActorSendAsync; | ||||
|             this.CreatedChannel = this.OnDmtpActorCreatedChannel; | ||||
|             this.m_udpSession = udpSession; | ||||
|             this.m_endPoint = endPoint; | ||||
|             this.Logger = logger; | ||||
|             this.Client = this; | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         private Task OnDmtpActorCreatedChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         { | ||||
|             this.pluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|             return this.pluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|         } | ||||
|  | ||||
|         public bool Created(IPluginsManager pluginsManager) | ||||
| @@ -117,5 +118,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|         { | ||||
|             this.m_udpSession.Send(this.m_endPoint, transferBytes); | ||||
|         } | ||||
|  | ||||
|         private Task RpcActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             return this.m_udpSession.SendAsync(this.m_endPoint, transferBytes); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -50,13 +50,17 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|         #region 字段 | ||||
|  | ||||
|         private readonly SemaphoreSlim m_semaphoreForConnect = new SemaphoreSlim(1, 1); | ||||
|         private readonly SemaphoreSlim m_semaphoreForSend = new SemaphoreSlim(1, 1); | ||||
|         private ClientWebSocket m_client; | ||||
|         private Func<string, IDmtpActor> m_findDmtpActor; | ||||
|         private ValueCounter m_receiveCounter; | ||||
|         private ValueCounter m_sendCounter; | ||||
|         private SealedDmtpActor m_dmtpActor; | ||||
|         private TcpDmtpAdapter m_smtpAdapter; | ||||
|         private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); | ||||
|         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||
|         private int m_receiveBufferSize = 1024 * 10; | ||||
|         private ValueCounter m_receiveCounter; | ||||
|         private int m_sendBufferSize = 1024 * 10; | ||||
|         private ValueCounter m_sendCounter; | ||||
|         private TcpDmtpAdapter m_dmtpAdapter; | ||||
|  | ||||
|         #endregion 字段 | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
| @@ -90,25 +94,21 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <inheritdoc/> | ||||
|         public DateTime LastSendTime => this.m_sendCounter.LastIncrement; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 未实现 | ||||
|         /// </summary> | ||||
|         public Func<ByteBlock, bool> OnHandleRawBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 未实现 | ||||
|         /// </summary> | ||||
|         public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IPluginsManager PluginsManager { get; private set; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public Protocol Protocol { get; set; } = DmtpUtility.DmtpProtocol; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int ReceiveBufferSize => this.m_receiveBufferSize; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IPHost RemoteIPHost { get; private set; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int SendBufferSize => this.m_sendBufferSize; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 发送<see cref="IDmtpActor"/>关闭消息。 | ||||
|         /// </summary> | ||||
| @@ -116,56 +116,15 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <returns></returns> | ||||
|         public void Close(string msg = "") | ||||
|         { | ||||
|             this.DmtpActor.Close(true, msg); | ||||
|             this.m_dmtpActor.SendClose(msg); | ||||
|             this.m_dmtpActor.Close(msg); | ||||
|             this.PrivateClose(msg); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public async Task ConnectAsync(int timeout = 5000) | ||||
|         public Task ConnectAsync(int timeout = 5000) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 await this.m_semaphore.WaitAsync(); | ||||
|                 if (this.IsHandshaked) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (this.m_client == null || this.m_client.State != WebSocketState.Open) | ||||
|                 { | ||||
|                     this.m_client.SafeDispose(); | ||||
|                     this.m_client = new ClientWebSocket(); | ||||
|                     await this.m_client.ConnectAsync(this.RemoteIPHost, default); | ||||
|  | ||||
|                     this.m_dmtpActor = new SealedDmtpActor(false) | ||||
|                     { | ||||
|                         OutputSend = this.OnDmtpActorSend, | ||||
|                         OnRouting = this.OnDmtpActorRouting, | ||||
|                         OnHandshaking = this.OnDmtpActorHandshaking, | ||||
|                         OnHandshaked = this.OnDmtpActorHandshaked, | ||||
|                         OnClose = this.OnDmtpActorClose, | ||||
|                         Logger = this.Logger, | ||||
|                         Client = this, | ||||
|                         OnFindDmtpActor = this.m_findDmtpActor, | ||||
|                         OnCreateChannel = this.OnDmtpActorCreateChannel | ||||
|                     }; | ||||
|  | ||||
|                     this.m_smtpAdapter = new TcpDmtpAdapter() | ||||
|                     { | ||||
|                         ReceivedCallBack = this.PrivateHandleReceivedData | ||||
|                     }; | ||||
|                     _ = this.BeginReceive(); | ||||
|                 } | ||||
|  | ||||
|                 this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), | ||||
|                     this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), | ||||
|                     timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); | ||||
|                 this.IsHandshaked = true; | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 this.m_semaphore.Release(); | ||||
|             } | ||||
|             return this.ConnectAsync(CancellationToken.None, timeout); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
| @@ -173,7 +132,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 await this.m_semaphore.WaitAsync(); | ||||
|                 await this.m_semaphoreForConnect.WaitAsync(); | ||||
|                 if (this.IsHandshaked) | ||||
|                 { | ||||
|                     return; | ||||
| @@ -188,17 +147,18 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                     this.m_dmtpActor = new SealedDmtpActor(false) | ||||
|                     { | ||||
|                         OutputSend = this.OnDmtpActorSend, | ||||
|                         OnRouting = this.OnDmtpActorRouting, | ||||
|                         OnHandshaking = this.OnDmtpActorHandshaking, | ||||
|                         OnHandshaked = this.OnDmtpActorHandshaked, | ||||
|                         OnClose = this.OnDmtpActorClose, | ||||
|                         OutputSendAsync = this.OnDmtpActorSendAsync, | ||||
|                         Routing = this.OnDmtpActorRouting, | ||||
|                         Handshaking = this.OnDmtpActorHandshaking, | ||||
|                         Handshaked = this.OnDmtpActorHandshaked, | ||||
|                         Closed = this.OnDmtpActorClose, | ||||
|                         Logger = this.Logger, | ||||
|                         Client = this, | ||||
|                         OnFindDmtpActor = this.m_findDmtpActor, | ||||
|                         OnCreateChannel = this.OnDmtpActorCreateChannel | ||||
|                     }; | ||||
|                         FindDmtpActor = this.m_findDmtpActor, | ||||
|                         CreatedChannel = this.OnDmtpActorCreateChannel | ||||
|                     }; ; | ||||
|  | ||||
|                     this.m_smtpAdapter = new TcpDmtpAdapter() | ||||
|                     this.m_dmtpAdapter = new TcpDmtpAdapter() | ||||
|                     { | ||||
|                         ReceivedCallBack = this.PrivateHandleReceivedData | ||||
|                     }; | ||||
| @@ -212,7 +172,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 this.m_semaphore.Release(); | ||||
|                 this.m_semaphoreForConnect.Release(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -316,7 +276,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                         byteBlock.SetLength(result.Count); | ||||
|                         this.m_receiveCounter.Increment(result.Count); | ||||
|  | ||||
|                         this.m_smtpAdapter.ReceivedInput(byteBlock); | ||||
|                         this.m_dmtpAdapter.ReceivedInput(byteBlock); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
| @@ -338,7 +298,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                     this.m_client.CloseAsync(WebSocketCloseStatus.NormalClosure, msg, CancellationToken.None); | ||||
|                     this.m_client.SafeDispose(); | ||||
|                     this.DmtpActor.SafeDispose(); | ||||
|                     this.m_smtpAdapter.SafeDispose(); | ||||
|                     this.m_dmtpAdapter.SafeDispose(); | ||||
|                     this.OnDisconnected(new DisconnectEventArgs(manual, msg)); | ||||
|                 } | ||||
|             } | ||||
| @@ -388,12 +348,12 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|         private void OnReceivePeriod(long value) | ||||
|         { | ||||
|             this.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value); | ||||
|             this.m_receiveBufferSize = TouchSocketUtility.HitBufferLength(value); | ||||
|         } | ||||
|  | ||||
|         private void OnSendPeriod(long value) | ||||
|         { | ||||
|             this.SendBufferSize = TouchSocketUtility.HitBufferLength(value); | ||||
|             this.m_sendBufferSize = TouchSocketUtility.HitBufferLength(value); | ||||
|         } | ||||
|  | ||||
|         private void PrivateClose(string msg) | ||||
| @@ -404,7 +364,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) | ||||
|         { | ||||
|             var message = (DmtpMessage)requestInfo; | ||||
|             if (!this.m_dmtpActor.InputReceivedData(message)) | ||||
|             if (!this.m_dmtpActor.InputReceivedData(message).GetFalseAwaitResult()) | ||||
|             { | ||||
|                 this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); | ||||
|             } | ||||
| @@ -412,71 +372,81 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|  | ||||
|         #region 内部委托绑定 | ||||
|  | ||||
|         private void OnDmtpActorClose(DmtpActor actor, string arg2) | ||||
|         private Task OnDmtpActorClose(DmtpActor actor, string arg2) | ||||
|         { | ||||
|             this.PrivateClose(arg2); | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||
|         { | ||||
|             this.OnCreateChannel(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|             return this.OnCreateChannel(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             this.OnHandshaked(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             return this.OnHandshaked(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             this.OnHandshaking(e); | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); | ||||
|             return this.OnHandshaking(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||
|         { | ||||
|             if (this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             this.OnRouting(e); | ||||
|             return this.OnRouting(e); | ||||
|         } | ||||
|  | ||||
|         private void OnDmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             for (var i = 0; i < transferBytes.Length; i++) | ||||
|             try | ||||
|             { | ||||
|                 Task task; | ||||
|                 if (i == transferBytes.Length - 1) | ||||
|                 this.m_semaphoreForSend.Wait(); | ||||
|                 for (var i = 0; i < transferBytes.Length; i++) | ||||
|                 { | ||||
|                     task = this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, true, CancellationToken.None); | ||||
|                     Task task; | ||||
|                     if (i == transferBytes.Length - 1) | ||||
|                     { | ||||
|                         task = this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, true, CancellationToken.None); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         task = this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, false, CancellationToken.None); | ||||
|                     } | ||||
|                     task.GetFalseAwaitResult(); | ||||
|                     this.m_sendCounter.Increment(transferBytes[i].Count); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     task = this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, false, CancellationToken.None); | ||||
|                 } | ||||
|                 task.ConfigureAwait(false); | ||||
|                 task.GetAwaiter().GetResult(); | ||||
|                 this.m_sendCounter.Increment(transferBytes[i].Count); | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 this.m_semaphoreForSend.Release(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private async Task OnDmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 await this.m_semaphoreForSend.WaitAsync(); | ||||
|                 for (var i = 0; i < transferBytes.Length; i++) | ||||
|                 { | ||||
|                     if (i == transferBytes.Length - 1) | ||||
|                     { | ||||
|                         await this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, true, CancellationToken.None); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         await this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, false, CancellationToken.None); | ||||
|                     } | ||||
|                     this.m_sendCounter.Increment(transferBytes[i].Count); | ||||
|                 } | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 this.m_semaphoreForSend.Release(); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         #endregion 内部委托绑定 | ||||
| @@ -487,38 +457,68 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// 当创建通道 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnCreateChannel(CreateChannelEventArgs e) | ||||
|         protected virtual async Task OnCreateChannel(CreateChannelEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 在完成握手连接时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 即将握手连接时 | ||||
|         /// </summary> | ||||
|         /// <param name="e">参数</param> | ||||
|         protected virtual void OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当需要转发路由包时 | ||||
|         /// </summary> | ||||
|         /// <param name="e"></param> | ||||
|         protected virtual void OnRouting(PackageRouterEventArgs e) | ||||
|         protected virtual async Task OnRouting(PackageRouterEventArgs e) | ||||
|         { | ||||
|             if (e.Handled) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e); | ||||
|         } | ||||
|  | ||||
|         #endregion 事件触发 | ||||
|  | ||||
|         #region Receiver | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 不支持该功能 | ||||
|         /// </summary> | ||||
|         /// <exception cref="NotSupportedException"></exception> | ||||
|         public void ClearReceiver() | ||||
|         { | ||||
|             throw new NotSupportedException("不支持该功能"); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 不支持该功能 | ||||
|         /// </summary> | ||||
| @@ -529,15 +529,6 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|             throw new NotSupportedException("不支持该功能"); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 不支持该功能 | ||||
|         /// </summary> | ||||
|         /// <exception cref="NotSupportedException"></exception> | ||||
|         public void ClearReceiver() | ||||
|         { | ||||
|             throw new NotSupportedException("不支持该功能"); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|         #endregion Receiver | ||||
|     } | ||||
| } | ||||
| @@ -10,6 +10,9 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Dmtp | ||||
| { | ||||
|     /// <summary> | ||||
|   | ||||
| @@ -22,10 +22,10 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|         /// <summary> | ||||
|         /// 创建一个<see cref="DmtpFileTransferActor"/> | ||||
|         /// </summary> | ||||
|         /// <param name="smtpActor"></param> | ||||
|         public DmtpFileTransferActor(IDmtpActor smtpActor) | ||||
|         /// <param name="dmtpActor"></param> | ||||
|         public DmtpFileTransferActor(IDmtpActor dmtpActor) | ||||
|         { | ||||
|             this.DmtpActor = smtpActor; | ||||
|             this.DmtpActor = dmtpActor; | ||||
|         } | ||||
|  | ||||
|         #region 委托 | ||||
| @@ -61,12 +61,8 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|  | ||||
|         #endregion 字段 | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 处理收到的消息 | ||||
|         /// </summary> | ||||
|         /// <param name="message"></param> | ||||
|         /// <returns></returns> | ||||
|         public bool InputReceivedData(DmtpMessage message) | ||||
|         /// <inheritdoc/> | ||||
|         public async Task<bool> InputReceivedData(DmtpMessage message) | ||||
|         { | ||||
|             var byteBlock = message.BodyByteBlock; | ||||
|             if (message.ProtocolFlags == this.m_pullFileResourceInfo_Request) | ||||
| @@ -77,9 +73,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFileResource.UnpackageRouter(byteBlock); | ||||
|                     if (waitFileResource.Route && this.DmtpActor.AllowRoute) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryRoute(RouteType.PullFile, waitFileResource)) | ||||
|                         if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.PullFile, waitFileResource))) | ||||
|                         { | ||||
|                             if (this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId, out var actor)) | ||||
|                             if (await this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId) is DmtpActor actor) | ||||
|                             { | ||||
|                                 actor.Send(this.m_pullFileResourceInfo_Request, byteBlock); | ||||
|                                 return true; | ||||
| @@ -101,7 +97,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     else | ||||
|                     { | ||||
|                         waitFileResource.UnpackageBody(byteBlock); | ||||
|                         Task.Factory.StartNew(this.RequestPullFileResourceInfo, waitFileResource); | ||||
|                         _ = Task.Factory.StartNew(this.RequestPullFileResourceInfo, waitFileResource); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
| @@ -118,7 +114,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFileResource.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitFileResource.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_pullFileResourceInfo_Response, byteBlock); | ||||
|                         } | ||||
| @@ -143,9 +139,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFileSection.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitFileSection.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_pullFileSection_Request, byteBlock); | ||||
|                             await actor.SendAsync(this.m_pullFileSection_Request, byteBlock); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
| @@ -153,7 +149,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                             waitFileSection.SwitchId(); | ||||
|                             byteBlock.Reset(); | ||||
|                             waitFileSection.Package(byteBlock); | ||||
|                             this.DmtpActor.Send(this.m_pullFileSection_Response, byteBlock); | ||||
|                             await this.DmtpActor.SendAsync(this.m_pullFileSection_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
| @@ -177,9 +173,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFileSection.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitFileSection.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_pullFileSection_Response, byteBlock); | ||||
|                             await actor.SendAsync(this.m_pullFileSection_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
| @@ -202,11 +198,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFileResource.UnpackageRouter(byteBlock); | ||||
|                     if (waitFileResource.Route && this.DmtpActor.AllowRoute) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryRoute(RouteType.PullFile, waitFileResource)) | ||||
|                         if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.PullFile, waitFileResource))) | ||||
|                         { | ||||
|                             if (this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId, out var actor)) | ||||
|                             if (await this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId) is DmtpActor actor) | ||||
|                             { | ||||
|                                 actor.Send(this.m_pushFileResourceInfo_Request, byteBlock); | ||||
|                                 await actor.SendAsync(this.m_pushFileResourceInfo_Request, byteBlock); | ||||
|                                 return true; | ||||
|                             } | ||||
|                             else | ||||
| @@ -221,12 +217,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                         byteBlock.Reset(); | ||||
|                         waitFileResource.SwitchId(); | ||||
|                         waitFileResource.Package(byteBlock); | ||||
|                         this.DmtpActor.Send(this.m_pushFileResourceInfo_Response, byteBlock); | ||||
|                         await this.DmtpActor.SendAsync(this.m_pushFileResourceInfo_Response, byteBlock); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         waitFileResource.UnpackageBody(byteBlock); | ||||
|                         Task.Factory.StartNew(this.RequestPushFileResourceInfo, waitFileResource); | ||||
|                         _ = this.RequestPushFileResourceInfo(waitFileResource); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
| @@ -243,9 +239,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFileResource.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitFileResource.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_pushFileResourceInfo_Response, byteBlock); | ||||
|                             await actor.SendAsync(this.m_pushFileResourceInfo_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
| @@ -268,9 +264,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFileSection.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitFileSection.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_pushFileSection_Request, byteBlock); | ||||
|                             await actor.SendAsync(this.m_pushFileSection_Request, byteBlock); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
| @@ -278,7 +274,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                             waitFileSection.SwitchId(); | ||||
|                             byteBlock.Reset(); | ||||
|                             waitFileSection.Package(byteBlock); | ||||
|                             this.DmtpActor.Send(this.m_pushFileSection_Response, byteBlock); | ||||
|                             await this.DmtpActor.SendAsync(this.m_pushFileSection_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
| @@ -303,9 +299,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFileSection.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitFileSection.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_pushFileSection_Response, byteBlock); | ||||
|                             await actor.SendAsync(this.m_pushFileSection_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
| @@ -328,9 +324,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFinishedPackage.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitFinishedPackage.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitFinishedPackage.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitFinishedPackage.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_finishedFileResourceInfo_Request, byteBlock); | ||||
|                             await actor.SendAsync(this.m_finishedFileResourceInfo_Request, byteBlock); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
| @@ -338,13 +334,13 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                             waitFinishedPackage.SwitchId(); | ||||
|                             byteBlock.Reset(); | ||||
|                             waitFinishedPackage.Package(byteBlock); | ||||
|                             this.DmtpActor.Send(this.m_finishedFileResourceInfo_Response, byteBlock); | ||||
|                             await this.DmtpActor.SendAsync(this.m_finishedFileResourceInfo_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         waitFinishedPackage.UnpackageBody(byteBlock); | ||||
|                         Task.Factory.StartNew(this.RequestFinishedFileResourceInfo, waitFinishedPackage); | ||||
|                         _ = this.RequestFinishedFileResourceInfo(waitFinishedPackage); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
| @@ -361,9 +357,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitFinishedPackage.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitFinishedPackage.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitFinishedPackage.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitFinishedPackage.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_finishedFileResourceInfo_Response, byteBlock); | ||||
|                             await actor.SendAsync(this.m_finishedFileResourceInfo_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
| @@ -386,11 +382,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitSmallFilePackage.UnpackageRouter(byteBlock); | ||||
|                     if (waitSmallFilePackage.Route && this.DmtpActor.AllowRoute) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryRoute(RouteType.PullFile, waitSmallFilePackage)) | ||||
|                         if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.PullFile, waitSmallFilePackage))) | ||||
|                         { | ||||
|                             if (this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId, out var actor)) | ||||
|                             if (await this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId) is DmtpActor actor) | ||||
|                             { | ||||
|                                 actor.Send(this.m_pullSmallFile_Request, byteBlock); | ||||
|                                 await actor.SendAsync(this.m_pullSmallFile_Request, byteBlock); | ||||
|                                 return true; | ||||
|                             } | ||||
|                             else | ||||
| @@ -405,12 +401,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                         byteBlock.Reset(); | ||||
|                         waitSmallFilePackage.SwitchId(); | ||||
|                         waitSmallFilePackage.Package(byteBlock); | ||||
|                         this.DmtpActor.Send(this.m_pullSmallFile_Response, byteBlock); | ||||
|                         await this.DmtpActor.SendAsync(this.m_pullSmallFile_Response, byteBlock); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         waitSmallFilePackage.UnpackageBody(byteBlock); | ||||
|                         Task.Factory.StartNew(this.RequestPullSmallFile, waitSmallFilePackage); | ||||
|                         _ = Task.Factory.StartNew(this.RequestPullSmallFile, waitSmallFilePackage); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
| @@ -427,9 +423,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitSmallFilePackage.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && waitSmallFilePackage.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_pullSmallFile_Response, byteBlock); | ||||
|                             await actor.SendAsync(this.m_pullSmallFile_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
| @@ -452,11 +448,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                     waitSmallFilePackage.UnpackageRouter(byteBlock); | ||||
|                     if (waitSmallFilePackage.Route && this.DmtpActor.AllowRoute) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryRoute(RouteType.PullFile, waitSmallFilePackage)) | ||||
|                         if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.PullFile, waitSmallFilePackage))) | ||||
|                         { | ||||
|                             if (this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId, out var actor)) | ||||
|                             if (await this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId) is DmtpActor actor) | ||||
|                             { | ||||
|                                 actor.Send(this.m_pushSmallFile_Request, byteBlock); | ||||
|                                 await actor.SendAsync(this.m_pushSmallFile_Request, byteBlock); | ||||
|                                 return true; | ||||
|                             } | ||||
|                             else | ||||
| @@ -472,12 +468,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                         byteBlock.Reset(); | ||||
|                         waitSmallFilePackage.SwitchId(); | ||||
|                         waitSmallFilePackage.Package(byteBlock); | ||||
|                         this.DmtpActor.Send(this.m_pushSmallFile_Response, byteBlock); | ||||
|                         await this.DmtpActor.SendAsync(this.m_pushSmallFile_Response, byteBlock); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         waitSmallFilePackage.UnpackageBody(byteBlock); | ||||
|                         Task.Factory.StartNew(this.RequestPushSmallFile, waitSmallFilePackage); | ||||
|                         _ = this.RequestPushSmallFile(waitSmallFilePackage); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
| @@ -495,9 +491,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|  | ||||
|                     if (this.DmtpActor.AllowRoute && waitSmallFilePackage.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId) is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_pushSmallFile_Response, byteBlock); | ||||
|                             await actor.SendAsync(this.m_pushSmallFile_Response, byteBlock); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
| @@ -568,24 +564,20 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|             return this.FileController.GetFullPath(this.m_rootPath, path); | ||||
|         } | ||||
|  | ||||
|         private bool TryFindDmtpFileTransferActor(string targetId, out DmtpFileTransferActor rpcActor) | ||||
|         private async Task<DmtpFileTransferActor> TryFindDmtpFileTransferActor(string targetId) | ||||
|         { | ||||
|             if (targetId == this.DmtpActor.Id) | ||||
|             { | ||||
|                 rpcActor = this; | ||||
|                 return true; | ||||
|                 return this; | ||||
|             } | ||||
|             if (this.DmtpActor.TryFindDmtpActor(targetId, out var smtpActor)) | ||||
|             if (await this.DmtpActor.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor dmtpActor) | ||||
|             { | ||||
|                 if (smtpActor.GetDmtpFileTransferActor() is DmtpFileTransferActor newActor) | ||||
|                 if (dmtpActor.GetDmtpFileTransferActor() is DmtpFileTransferActor newActor) | ||||
|                 { | ||||
|                     rpcActor = newActor; | ||||
|                     return true; | ||||
|                     return newActor; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             rpcActor = default; | ||||
|             return false; | ||||
|             return default; | ||||
|         } | ||||
|  | ||||
|         #region Id传输 | ||||
| @@ -598,9 +590,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 return this.PrivateFinishedFileResourceInfo(targetId, fileResourceInfo, code, metadata, timeout, token); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor) | ||||
|             { | ||||
|                 return rpcActor.FinishedFileResourceInfo(fileResourceInfo, code, metadata, timeout, token); | ||||
|                 return actor.FinishedFileResourceInfo(fileResourceInfo, code, metadata, timeout, token); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -625,9 +617,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 return this.PrivatePullFileResourceInfo(targetId, path, metadata, fileSectionSize, timeout, token); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor) | ||||
|             { | ||||
|                 return rpcActor.PullFileResourceInfo(path, metadata, fileSectionSize, timeout, token); | ||||
|                 return actor.PullFileResourceInfo(path, metadata, fileSectionSize, timeout, token); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -652,9 +644,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 return this.PrivatePullFileSection(targetId, fileSection, timeout, token); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor) | ||||
|             { | ||||
|                 return rpcActor.PullFileSection(fileSection, timeout, token); | ||||
|                 return actor.PullFileSection(fileSection, timeout, token); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -679,9 +671,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 return this.PrivatePushFileResourceInfo(targetId, savePath, fileResourceLocator, metadata, timeout, token); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor) | ||||
|             { | ||||
|                 return rpcActor.PushFileResourceInfo(savePath, fileResourceLocator, metadata, timeout, token); | ||||
|                 return actor.PushFileResourceInfo(savePath, fileResourceLocator, metadata, timeout, token); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -715,9 +707,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 return this.PrivatePushFileSection(targetId, fileResourceLocator, fileSection, timeout, token); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor) | ||||
|             { | ||||
|                 return rpcActor.PushFileSection(fileResourceLocator, fileSection, timeout, token); | ||||
|                 return actor.PushFileSection(fileResourceLocator, fileSection, timeout, token); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -1261,7 +1253,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 { | ||||
|                     waitFinishedPackage.SwitchId(); | ||||
|                     waitFinishedPackage.Package(byteBlock); | ||||
|                     this.DmtpActor.Send(this.m_finishedFileResourceInfo_Response, byteBlock); | ||||
|                     await this.DmtpActor.SendAsync(this.m_finishedFileResourceInfo_Response, byteBlock); | ||||
|                 } | ||||
|  | ||||
|                 var args = new FileTransferedEventArgs(transferType, waitFinishedPackage?.Metadata, resourceInfo?.FileInfo, waitFinishedPackage.Code == ResultCode.Canceled ? Result.Canceled : resultThis) | ||||
| @@ -1454,7 +1446,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 { | ||||
|                     waitFileResource.SwitchId(); | ||||
|                     waitFileResource.Package(byteBlock); | ||||
|                     this.DmtpActor.Send(this.m_pushFileResourceInfo_Response, byteBlock); | ||||
|                     await this.DmtpActor.SendAsync(this.m_pushFileResourceInfo_Response, byteBlock); | ||||
|                 } | ||||
|             } | ||||
|             catch | ||||
| @@ -1528,7 +1520,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|         /// <inheritdoc/> | ||||
|         public PullSmallFileResult PullSmallFile(string targetId, string path, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) | ||||
|         { | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var actor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor) | ||||
|             { | ||||
|                 return actor.PullSmallFile(path, metadata, timeout, token); | ||||
|             } | ||||
| @@ -1565,9 +1557,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|         /// <inheritdoc/> | ||||
|         public Result PushSmallFile(string targetId, string savePath, FileInfo fileInfo, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) | ||||
|         { | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor) | ||||
|             { | ||||
|                 return rpcActor.PushSmallFile(savePath, fileInfo, metadata, timeout, token); | ||||
|                 return actor.PushSmallFile(savePath, fileInfo, metadata, timeout, token); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -1827,7 +1819,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 { | ||||
|                     waitSmallFilePackage.SwitchId(); | ||||
|                     waitSmallFilePackage.Package(byteBlock); | ||||
|                     this.DmtpActor.Send(this.m_pullSmallFile_Response, byteBlock); | ||||
|                     await this.DmtpActor.SendAsync(this.m_pullSmallFile_Response, byteBlock); | ||||
|                 } | ||||
|  | ||||
|                 var resultArgs = new FileTransferedEventArgs( | ||||
| @@ -1891,7 +1883,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
|                 { | ||||
|                     waitSmallFilePackage.Package(byteBlock); | ||||
|                     this.DmtpActor.Send(this.m_pushSmallFile_Response, byteBlock); | ||||
|                     await this.DmtpActor.SendAsync(this.m_pushSmallFile_Response, byteBlock); | ||||
|                 } | ||||
|  | ||||
|                 var resultArgs = new FileTransferedEventArgs( | ||||
|   | ||||
| @@ -59,12 +59,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|         /// </summary> | ||||
|         public int TryCount { get; set; } = 10; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 设置结果状态 | ||||
|         /// </summary> | ||||
|         /// <param name="result"></param> | ||||
|         /// <returns></returns> | ||||
|         public Result SetResult(Result result) | ||||
|         internal Result SetResult(Result result) | ||||
|         { | ||||
|             this.Result = result; | ||||
|             return result; | ||||
|   | ||||
| @@ -48,7 +48,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|         /// <inheritdoc/> | ||||
|         public Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             var smtpFileTransferActor = new DmtpFileTransferActor(client.DmtpActor) | ||||
|             var dmtpFileTransferActor = new DmtpFileTransferActor(client.DmtpActor) | ||||
|             { | ||||
|                 FileController = this.m_fileResourceController, | ||||
|                 OnFileTransfering = this.OnFileTransfering, | ||||
| @@ -56,25 +56,25 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|                 RootPath = this.RootPath, | ||||
|                 MaxSmallFileLength = this.MaxSmallFileLength | ||||
|             }; | ||||
|             smtpFileTransferActor.SetProtocolFlags(this.StartProtocol); | ||||
|             client.DmtpActor.SetDmtpFileTransferActor(smtpFileTransferActor); | ||||
|             dmtpFileTransferActor.SetProtocolFlags(this.StartProtocol); | ||||
|             client.DmtpActor.SetDmtpFileTransferActor(dmtpFileTransferActor); | ||||
|  | ||||
|             return e.InvokeNext(); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e) | ||||
|         public async Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e) | ||||
|         { | ||||
|             if (client.DmtpActor.GetDmtpFileTransferActor() is DmtpFileTransferActor smtpFileTransferActor) | ||||
|             if (client.DmtpActor.GetDmtpFileTransferActor() is DmtpFileTransferActor dmtpFileTransferActor) | ||||
|             { | ||||
|                 if (smtpFileTransferActor.InputReceivedData(e.DmtpMessage)) | ||||
|                 if (await dmtpFileTransferActor.InputReceivedData(e.DmtpMessage)) | ||||
|                 { | ||||
|                     e.Handled = true; | ||||
|                     return EasyTask.CompletedTask; | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return e.InvokeNext(); | ||||
|             await e.InvokeNext(); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc cref="IDmtpFileTransferActor.MaxSmallFileLength"/> | ||||
|   | ||||
| @@ -48,21 +48,21 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | ||||
|         /// <summary> | ||||
|         /// 从<see cref="DmtpActor"/>中获取<see cref="IDmtpFileTransferActor"/> | ||||
|         /// </summary> | ||||
|         /// <param name="smtpActor"></param> | ||||
|         /// <param name="dmtpActor"></param> | ||||
|         /// <returns></returns> | ||||
|         public static IDmtpFileTransferActor GetDmtpFileTransferActor(this IDmtpActor smtpActor) | ||||
|         public static IDmtpFileTransferActor GetDmtpFileTransferActor(this IDmtpActor dmtpActor) | ||||
|         { | ||||
|             return smtpActor.GetValue(DmtpFileTransferActorProperty); | ||||
|             return dmtpActor.GetValue(DmtpFileTransferActorProperty); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 向<see cref="DmtpActor"/>中设置<see cref="DmtpFileTransferActor"/> | ||||
|         /// </summary> | ||||
|         /// <param name="smtpActor"></param> | ||||
|         /// <param name="smtpRpcActor"></param> | ||||
|         internal static void SetDmtpFileTransferActor(this IDmtpActor smtpActor, DmtpFileTransferActor smtpRpcActor) | ||||
|         /// <param name="dmtpActor"></param> | ||||
|         /// <param name="dmtpRpcActor"></param> | ||||
|         internal static void SetDmtpFileTransferActor(this IDmtpActor dmtpActor, DmtpFileTransferActor dmtpRpcActor) | ||||
|         { | ||||
|             smtpActor.SetValue(DmtpFileTransferActorProperty, smtpRpcActor); | ||||
|             dmtpActor.SetValue(DmtpFileTransferActorProperty, dmtpRpcActor); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|   | ||||
| @@ -22,10 +22,10 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | ||||
|         /// <summary> | ||||
|         /// DmtpRedisActor | ||||
|         /// </summary> | ||||
|         /// <param name="smtpActor"></param> | ||||
|         public DmtpRedisActor(IDmtpActor smtpActor) | ||||
|         /// <param name="dmtpActor"></param> | ||||
|         public DmtpRedisActor(IDmtpActor dmtpActor) | ||||
|         { | ||||
|             this.DmtpActor = smtpActor; | ||||
|             this.DmtpActor = dmtpActor; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
| @@ -241,7 +241,7 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | ||||
|         /// </summary> | ||||
|         /// <param name="message"></param> | ||||
|         /// <returns></returns> | ||||
|         public bool InputReceivedData(DmtpMessage message) | ||||
|         public async Task<bool> InputReceivedData(DmtpMessage message) | ||||
|         { | ||||
|             if (message.ProtocolFlags == this.m_redis_Request) | ||||
|             { | ||||
| @@ -311,7 +311,7 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
|                 { | ||||
|                     waitResult.Package(byteBlock); | ||||
|                     this.DmtpActor.Send(this.m_redis_Response, byteBlock); | ||||
|                     await this.DmtpActor.SendAsync(this.m_redis_Response, byteBlock); | ||||
|                 } | ||||
|                 return true; | ||||
|             } | ||||
|   | ||||
| @@ -22,6 +22,8 @@ | ||||
| //  感谢您的下载和使用 | ||||
| //------------------------------------------------------------------------------ | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
|  | ||||
| using ThingsGateway.Foundation.Resources; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Dmtp.Redis | ||||
| @@ -52,16 +54,16 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | ||||
|         /// <summary> | ||||
|         /// 从<see cref="DmtpActor"/>中获得<see cref="IDmtpRedisActor"/> | ||||
|         /// </summary> | ||||
|         /// <param name="smtpActor"></param> | ||||
|         /// <param name="dmtpActor"></param> | ||||
|         /// <returns></returns> | ||||
|         public static IDmtpRedisActor GetDmtpRedisActor(this IDmtpActor smtpActor) | ||||
|         public static IDmtpRedisActor GetDmtpRedisActor(this IDmtpActor dmtpActor) | ||||
|         { | ||||
|             return smtpActor.GetValue(DmtpRedisActorProperty); | ||||
|             return dmtpActor.GetValue(DmtpRedisActorProperty); | ||||
|         } | ||||
|  | ||||
|         internal static void SetStmpRedisActor(this IDmtpActor smtpActor, DmtpRedisActor redisClient) | ||||
|         internal static void SetStmpRedisActor(this IDmtpActor dmtpActor, DmtpRedisActor redisClient) | ||||
|         { | ||||
|             smtpActor.SetValue(DmtpRedisActorProperty, redisClient); | ||||
|             dmtpActor.SetValue(DmtpRedisActorProperty, redisClient); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|   | ||||
| @@ -58,30 +58,30 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | ||||
|         /// <inheritdoc/> | ||||
|         public Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             var smtpRedisActor = new DmtpRedisActor(client.DmtpActor) | ||||
|             var dmtpRedisActor = new DmtpRedisActor(client.DmtpActor) | ||||
|             { | ||||
|                 ICache = this.ICache, | ||||
|                 Converter = this.Converter | ||||
|             }; | ||||
|  | ||||
|             smtpRedisActor.SetProtocolFlags(this.StartProtocol); | ||||
|             client.DmtpActor.SetStmpRedisActor(smtpRedisActor); | ||||
|             dmtpRedisActor.SetProtocolFlags(this.StartProtocol); | ||||
|             client.DmtpActor.SetStmpRedisActor(dmtpRedisActor); | ||||
|  | ||||
|             return e.InvokeNext(); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e) | ||||
|         public async Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e) | ||||
|         { | ||||
|             if (client.DmtpActor.GetDmtpRedisActor() is DmtpRedisActor redisClient) | ||||
|             { | ||||
|                 if (redisClient.InputReceivedData(e.DmtpMessage)) | ||||
|                 if (await redisClient.InputReceivedData(e.DmtpMessage)) | ||||
|                 { | ||||
|                     e.Handled = true; | ||||
|                     return EasyTask.CompletedTask; | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             return e.InvokeNext(); | ||||
|             await e.InvokeNext(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|   | ||||
| @@ -36,10 +36,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|         /// <summary> | ||||
|         /// 创建一个DmtpRpcActor | ||||
|         /// </summary> | ||||
|         /// <param name="smtpActor"></param> | ||||
|         public DmtpRpcActor(IDmtpActor smtpActor) | ||||
|         /// <param name="dmtpActor"></param> | ||||
|         public DmtpRpcActor(IDmtpActor dmtpActor) | ||||
|         { | ||||
|             this.DmtpActor = smtpActor; | ||||
|             this.DmtpActor = dmtpActor; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
| @@ -69,7 +69,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|         /// </summary> | ||||
|         /// <param name="message"></param> | ||||
|         /// <returns></returns> | ||||
|         public bool InputReceivedData(DmtpMessage message) | ||||
|         public async Task<bool> InputReceivedData(DmtpMessage message) | ||||
|         { | ||||
|             var byteBlock = message.BodyByteBlock; | ||||
|  | ||||
| @@ -77,14 +77,13 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     //Console.WriteLine(byteBlock.Len); | ||||
|                     var rpcPackage = new DmtpRpcPackage(); | ||||
|                     rpcPackage.UnpackageRouter(byteBlock); | ||||
|                     if (rpcPackage.Route && this.DmtpActor.AllowRoute) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryRoute(RouteType.Rpc, rpcPackage)) | ||||
|                         if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.Rpc, rpcPackage)).ConfigureFalseAwait()) | ||||
|                         { | ||||
|                             if (this.DmtpActor.TryFindDmtpActor(rpcPackage.TargetId, out var actor)) | ||||
|                             if (await this.DmtpActor.TryFindDmtpActor(rpcPackage.TargetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|                             { | ||||
|                                 actor.Send(this.m_invoke_Request, byteBlock); | ||||
|                                 return true; | ||||
| @@ -108,8 +107,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     else | ||||
|                     { | ||||
|                         rpcPackage.UnpackageBody(byteBlock); | ||||
|                         Task.Factory.StartNew(this.InvokeThis, rpcPackage); | ||||
|                         //this.InvokeThis(rpcPackage); | ||||
|                         _ = Task.Factory.StartNew(this.InvokeThis, rpcPackage); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
| @@ -126,7 +124,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     rpcPackage.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && rpcPackage.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(rpcPackage.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(rpcPackage.TargetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_invoke_Response, byteBlock); | ||||
|                         } | ||||
| @@ -151,7 +149,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     canceledPackage.UnpackageRouter(byteBlock); | ||||
|                     if (this.DmtpActor.AllowRoute && canceledPackage.Route) | ||||
|                     { | ||||
|                         if (this.DmtpActor.TryFindDmtpActor(canceledPackage.TargetId, out var actor)) | ||||
|                         if (await this.DmtpActor.TryFindDmtpActor(canceledPackage.TargetId).ConfigureFalseAwait() is DmtpActor actor) | ||||
|                         { | ||||
|                             actor.Send(this.m_cancelInvoke, byteBlock); | ||||
|                         } | ||||
| @@ -203,7 +201,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|             try | ||||
|             { | ||||
|                 var rpcPackage = (DmtpRpcPackage)o; | ||||
|                 //Console.WriteLine(rpcPackage.MethodName); | ||||
|  | ||||
|                 var psData = rpcPackage.ParametersBytes; | ||||
|                 if (rpcPackage.Feedback == FeedbackType.WaitSend) | ||||
|                 { | ||||
| @@ -227,7 +225,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|                 var invokeResult = new InvokeResult(); | ||||
|                 object[] ps = null; | ||||
|                 var methodInstance = this.GetInvokeMethod?.Invoke(rpcPackage.MethodName); | ||||
|                 var methodInstance = this.GetInvokeMethod.Invoke(rpcPackage.MethodName); | ||||
|                 DmtpRpcCallContext callContext = null; | ||||
|                 if (methodInstance != null) | ||||
|                 { | ||||
| @@ -242,7 +240,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                                 DmtpRpcPackage = rpcPackage | ||||
|                             }; | ||||
|                             this.TryAdd(rpcPackage.Sign, callContext); | ||||
|                             if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext)) | ||||
|                             if (methodInstance.IncludeCallContext) | ||||
|                             { | ||||
|                                 ps = new object[methodInstance.ParameterTypes.Length]; | ||||
|                                 ps[0] = callContext; | ||||
| @@ -283,7 +281,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     { | ||||
|                         transientRpcServer.CallContext = callContext; | ||||
|                     } | ||||
|                     invokeResult = await RpcStore.ExecuteAsync(rpcServer, ps, callContext); | ||||
|                     invokeResult = await RpcStore.ExecuteAsync(rpcServer, ps, callContext).ConfigureFalseAwait(); | ||||
|                 } | ||||
|  | ||||
|                 if (rpcPackage.Feedback == FeedbackType.OnlySend) | ||||
| @@ -316,7 +314,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                                 rpcPackage.ParametersBytes = new List<byte[]>(); | ||||
|  | ||||
|                                 var i = 0; | ||||
|                                 if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext)) | ||||
|                                 if (methodInstance.IncludeCallContext) | ||||
|                                 { | ||||
|                                     i = 1; | ||||
|                                 } | ||||
| @@ -369,24 +367,20 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private bool TryFindDmtpRpcActor(string targetId, out DmtpRpcActor rpcActor) | ||||
|         private async Task<DmtpRpcActor> TryFindDmtpRpcActor(string targetId) | ||||
|         { | ||||
|             if (targetId == this.DmtpActor.Id) | ||||
|             { | ||||
|                 rpcActor = this; | ||||
|                 return true; | ||||
|                 return this; | ||||
|             } | ||||
|             if (this.DmtpActor.TryFindDmtpActor(targetId, out var smtpActor)) | ||||
|             if (await this.DmtpActor.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor dmtpActor) | ||||
|             { | ||||
|                 if (smtpActor.GetDmtpRpcActor() is DmtpRpcActor newActor) | ||||
|                 if (dmtpActor.GetDmtpRpcActor() is DmtpRpcActor newActor) | ||||
|                 { | ||||
|                     rpcActor = newActor; | ||||
|                     return true; | ||||
|                     return newActor; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             rpcActor = default; | ||||
|             return false; | ||||
|             return default; | ||||
|         } | ||||
|  | ||||
|         #region Rpc | ||||
| @@ -504,8 +498,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetWaitData(rpcPackage); | ||||
|  | ||||
|  | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
| @@ -532,7 +524,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -689,8 +680,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetWaitData(rpcPackage); | ||||
|  | ||||
|  | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
| @@ -722,7 +711,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -779,8 +767,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetWaitDataAsync(rpcPackage); | ||||
|  | ||||
|  | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
| @@ -818,7 +804,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|                     case FeedbackType.WaitSend: | ||||
|                         { | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()) | ||||
|                             { | ||||
|                                 case WaitDataStatus.SetRunning: | ||||
|                                     break; | ||||
| @@ -832,7 +818,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                         } | ||||
|                     case FeedbackType.WaitInvoke: | ||||
|                         { | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()) | ||||
|                             { | ||||
|                                 case WaitDataStatus.SetRunning: | ||||
|                                     { | ||||
| @@ -898,7 +884,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -907,7 +892,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                         } | ||||
|                     case FeedbackType.WaitSend: | ||||
|                         { | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()) | ||||
|                             { | ||||
|                                 case WaitDataStatus.Overtime: | ||||
|                                     { | ||||
| @@ -918,7 +903,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                         } | ||||
|                     case FeedbackType.WaitInvoke: | ||||
|                         { | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()) | ||||
|                             { | ||||
|                                 case WaitDataStatus.SetRunning: | ||||
|                                     { | ||||
| @@ -961,7 +946,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var actor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId).GetFalseAwaitResult() is DmtpRpcActor actor) | ||||
|             { | ||||
|                 actor.Invoke(invokeKey, invokeOption, parameters); | ||||
|                 return; | ||||
| @@ -977,7 +962,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); | ||||
|  | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
| @@ -1009,7 +993,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -1069,9 +1052,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId).GetFalseAwaitResult() is DmtpRpcActor actor) | ||||
|             { | ||||
|                 return rpcActor.Invoke(returnType, invokeKey, invokeOption, parameters); | ||||
|                 return actor.Invoke(returnType, invokeKey, invokeOption, parameters); | ||||
|             } | ||||
|  | ||||
|             var rpcPackage = new DmtpRpcPackage | ||||
| @@ -1084,10 +1067,8 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); | ||||
|  | ||||
|  | ||||
|             try | ||||
|             { | ||||
|  | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
|                 { | ||||
|                     if (invokeOption == default) | ||||
| @@ -1116,7 +1097,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -1175,9 +1155,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId).GetFalseAwaitResult() is DmtpRpcActor actor) | ||||
|             { | ||||
|                 rpcActor.Invoke(invokeKey, invokeOption, ref parameters, types); | ||||
|                 actor.Invoke(invokeKey, invokeOption, ref parameters, types); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -1191,7 +1171,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); | ||||
|  | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
| @@ -1219,7 +1198,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -1289,9 +1267,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId).GetFalseAwaitResult() is DmtpRpcActor actor) | ||||
|             { | ||||
|                 return rpcActor.Invoke(returnType, invokeKey, invokeOption, ref parameters, types); | ||||
|                 return actor.Invoke(returnType, invokeKey, invokeOption, ref parameters, types); | ||||
|             } | ||||
|  | ||||
|             var rpcPackage = new DmtpRpcPackage | ||||
| @@ -1304,7 +1282,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); | ||||
|  | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
| @@ -1330,7 +1307,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -1400,9 +1376,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var actor)) | ||||
|             if (this.DmtpActor.AllowRoute && await this.TryFindDmtpRpcActor(targetId).ConfigureFalseAwait() is DmtpRpcActor actor) | ||||
|             { | ||||
|                 await actor.InvokeAsync(invokeKey, invokeOption, parameters); | ||||
|                 await actor.InvokeAsync(invokeKey, invokeOption, parameters).ConfigureFalseAwait(); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -1416,7 +1392,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitDataAsync(rpcPackage); | ||||
|  | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 using (var byteBlock = new ByteBlock()) | ||||
| @@ -1448,7 +1423,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -1456,7 +1430,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|                     case FeedbackType.WaitSend: | ||||
|                         { | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()) | ||||
|                             { | ||||
|                                 case WaitDataStatus.SetRunning: | ||||
|                                     break; | ||||
| @@ -1470,7 +1444,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                         } | ||||
|                     case FeedbackType.WaitInvoke: | ||||
|                         { | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()) | ||||
|                             { | ||||
|                                 case WaitDataStatus.SetRunning: | ||||
|                                     { | ||||
| @@ -1508,9 +1482,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); | ||||
|             } | ||||
|  | ||||
|             if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var rpcActor)) | ||||
|             if (this.DmtpActor.AllowRoute && await this.TryFindDmtpRpcActor(targetId).ConfigureFalseAwait() is DmtpRpcActor actor) | ||||
|             { | ||||
|                 return await rpcActor.InvokeAsync(returnType, invokeKey, invokeOption, parameters); | ||||
|                 return await actor.InvokeAsync(returnType, invokeKey, invokeOption, parameters).ConfigureFalseAwait(); | ||||
|             } | ||||
|  | ||||
|             var rpcPackage = new DmtpRpcPackage | ||||
| @@ -1553,8 +1527,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|  | ||||
|                 switch (invokeOption.FeedbackType) | ||||
|                 { | ||||
|                     case FeedbackType.OnlySend: | ||||
| @@ -1563,7 +1535,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                         } | ||||
|                     case FeedbackType.WaitSend: | ||||
|                         { | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()) | ||||
|                             { | ||||
|                                 case WaitDataStatus.Overtime: | ||||
|                                     { | ||||
| @@ -1574,7 +1546,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|                         } | ||||
|                     case FeedbackType.WaitInvoke: | ||||
|                         { | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) | ||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()) | ||||
|                             { | ||||
|                                 case WaitDataStatus.SetRunning: | ||||
|                                     { | ||||
|   | ||||
| @@ -42,11 +42,11 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|         /// <summary> | ||||
|         /// 从<see cref="DmtpActor"/>中获取<see cref="IDmtpRpcActor"/> | ||||
|         /// </summary> | ||||
|         /// <param name="smtpActor"></param> | ||||
|         /// <param name="dmtpActor"></param> | ||||
|         /// <returns></returns> | ||||
|         public static IDmtpRpcActor GetDmtpRpcActor(this IDmtpActor smtpActor) | ||||
|         public static IDmtpRpcActor GetDmtpRpcActor(this IDmtpActor dmtpActor) | ||||
|         { | ||||
|             return smtpActor.GetValue(DmtpRpcActorProperty); | ||||
|             return dmtpActor.GetValue(DmtpRpcActorProperty); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -57,12 +57,12 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|         /// <exception cref="ArgumentNullException"></exception> | ||||
|         public static IDmtpRpcActor GetDmtpRpcActor(this IDmtpActorObject client) | ||||
|         { | ||||
|             var smtpRpcActor = client.DmtpActor.GetDmtpRpcActor(); | ||||
|             if (smtpRpcActor is null) | ||||
|             var dmtpRpcActor = client.DmtpActor.GetDmtpRpcActor(); | ||||
|             if (dmtpRpcActor is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(smtpRpcActor), TouchSocketDmtpResource.DmtpRpcActorArgumentNull.GetDescription()); | ||||
|                 throw new ArgumentNullException(nameof(dmtpRpcActor), TouchSocketDmtpResource.DmtpRpcActorArgumentNull.GetDescription()); | ||||
|             } | ||||
|             return smtpRpcActor; | ||||
|             return dmtpRpcActor; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -73,22 +73,22 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|         /// <exception cref="ArgumentNullException"></exception> | ||||
|         public static TDmtpRpcActor GetDmtpRpcActor<TDmtpRpcActor>(this IDmtpActorObject client) where TDmtpRpcActor : IDmtpRpcActor | ||||
|         { | ||||
|             var smtpRpcActor = client.DmtpActor.GetDmtpRpcActor(); | ||||
|             if (smtpRpcActor is null) | ||||
|             var dmtpRpcActor = client.DmtpActor.GetDmtpRpcActor(); | ||||
|             if (dmtpRpcActor is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(smtpRpcActor), TouchSocketDmtpResource.DmtpRpcActorArgumentNull.GetDescription()); | ||||
|                 throw new ArgumentNullException(nameof(dmtpRpcActor), TouchSocketDmtpResource.DmtpRpcActorArgumentNull.GetDescription()); | ||||
|             } | ||||
|             return (TDmtpRpcActor)smtpRpcActor; | ||||
|             return (TDmtpRpcActor)dmtpRpcActor; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 向<see cref="DmtpActor"/>中设置<see cref="IDmtpRpcActor"/> | ||||
|         /// </summary> | ||||
|         /// <param name="smtpActor"></param> | ||||
|         /// <param name="smtpRpcActor"></param> | ||||
|         internal static void SetDmtpRpcActor(this IDmtpActor smtpActor, IDmtpRpcActor smtpRpcActor) | ||||
|         /// <param name="dmtpActor"></param> | ||||
|         /// <param name="dmtpRpcActor"></param> | ||||
|         internal static void SetDmtpRpcActor(this IDmtpActor dmtpActor, IDmtpRpcActor dmtpRpcActor) | ||||
|         { | ||||
|             smtpActor.SetValue(DmtpRpcActorProperty, smtpRpcActor); | ||||
|             dmtpActor.SetValue(DmtpRpcActorProperty, dmtpRpcActor); | ||||
|         } | ||||
|  | ||||
|         #region 插件扩展 | ||||
|   | ||||
| @@ -94,9 +94,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|             return this.ActionMap.GetMethodInstance(name); | ||||
|         } | ||||
|  | ||||
|         private DmtpRpcActor PrivateCreateDmtpRpcActor(IDmtpActor smtpActor) | ||||
|         private DmtpRpcActor PrivateCreateDmtpRpcActor(IDmtpActor dmtpActor) | ||||
|         { | ||||
|             return new DmtpRpcActor(smtpActor); | ||||
|             return new DmtpRpcActor(dmtpActor); | ||||
|         } | ||||
|  | ||||
|         #region Rpc配置 | ||||
| @@ -135,31 +135,30 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|             pluginsManager.Add<IDmtpActorObject, DmtpMessageEventArgs>(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this.OnDmtpReceived); | ||||
|         } | ||||
|  | ||||
|         private Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e) | ||||
|         private async Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e) | ||||
|         { | ||||
|             var smtpRpcActor = CreateDmtpRpcActor(client.DmtpActor); | ||||
|             smtpRpcActor.RpcStore = this.RpcStore; | ||||
|             smtpRpcActor.SerializationSelector = this.SerializationSelector; | ||||
|             smtpRpcActor.GetInvokeMethod = this.GetInvokeMethod; | ||||
|             var dmtpRpcActor = this.CreateDmtpRpcActor(client.DmtpActor); | ||||
|             dmtpRpcActor.RpcStore = this.RpcStore; | ||||
|             dmtpRpcActor.SerializationSelector = this.SerializationSelector; | ||||
|             dmtpRpcActor.GetInvokeMethod = this.GetInvokeMethod; | ||||
|  | ||||
|             smtpRpcActor.SetProtocolFlags(this.StartProtocol); | ||||
|             client.DmtpActor.SetDmtpRpcActor(smtpRpcActor); | ||||
|             dmtpRpcActor.SetProtocolFlags(this.StartProtocol); | ||||
|             client.DmtpActor.SetDmtpRpcActor(dmtpRpcActor); | ||||
|  | ||||
|             return e.InvokeNext(); | ||||
|             await e.InvokeNext(); | ||||
|         } | ||||
|  | ||||
|         private Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e) | ||||
|         private async Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e) | ||||
|         { | ||||
|             if (client.DmtpActor.GetDmtpRpcActor() is DmtpRpcActor smtpRpcActor) | ||||
|             if (client.DmtpActor.GetDmtpRpcActor() is DmtpRpcActor dmtpRpcActor) | ||||
|             { | ||||
|                 if (smtpRpcActor.InputReceivedData(e.DmtpMessage)) | ||||
|                 if (await dmtpRpcActor.InputReceivedData(e.DmtpMessage).ConfigureFalseAwait()) | ||||
|                 { | ||||
|                     e.Handled = true; | ||||
|                     return EasyTask.CompletedTask; | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return e.InvokeNext(); | ||||
|             await e.InvokeNext(); | ||||
|         } | ||||
|  | ||||
|         #endregion Config | ||||
|   | ||||
| @@ -108,10 +108,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | ||||
|  | ||||
|         internal void LoadInvokeOption(IInvokeOption option) | ||||
|         { | ||||
|             if (option is DmtpInvokeOption smtpInvokeOption) | ||||
|             if (option is DmtpInvokeOption dmtpInvokeOption) | ||||
|             { | ||||
|                 this.Feedback = smtpInvokeOption.FeedbackType; | ||||
|                 this.SerializationType = smtpInvokeOption.SerializationType; | ||||
|                 this.Feedback = dmtpInvokeOption.FeedbackType; | ||||
|                 this.SerializationType = dmtpInvokeOption.SerializationType; | ||||
|             } | ||||
|             else if (option is InvokeOption invokeOption) | ||||
|             { | ||||
|   | ||||
| @@ -27,6 +27,6 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// </summary> | ||||
|         /// <param name="message"></param> | ||||
|         /// <returns>当满足本协议时,应当返回<see langword="true"/>,其他时候应该返回<see langword="false"/>.</returns> | ||||
|         public bool InputReceivedData(DmtpMessage message); | ||||
|         public Task<bool> InputReceivedData(DmtpMessage message); | ||||
|     } | ||||
| } | ||||
| @@ -58,7 +58,7 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|                         failedCount++; | ||||
|                         if (failedCount > this.MaxFailCount) | ||||
|                         { | ||||
|                             client.DmtpActor.Close(true, "自动心跳失败次数达到最大,已断开连接。"); | ||||
|                             client.DmtpActor.Close("自动心跳失败次数达到最大,已断开连接。"); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
| @@ -18,8 +18,8 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|     public class DmtpRouteService : IDmtpRouteService | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// 查找路由的委托 | ||||
|         /// <inheritdoc/> | ||||
|         /// </summary> | ||||
|         public Func<string, IDmtpActor> FindDmtpActor { get; set; } | ||||
|         public Func<string, Task<IDmtpActor>> FindDmtpActor { get; set; } | ||||
|     } | ||||
| } | ||||
| @@ -31,12 +31,26 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// </summary> | ||||
|         /// <param name="container"></param> | ||||
|         /// <param name="func"></param> | ||||
|         public static void AddDmtpRouteService(this IContainer container, Func<string, IDmtpActor> func) | ||||
|         public static void AddDmtpRouteService(this IContainer container, Func<string, Task<IDmtpActor>> func) | ||||
|         { | ||||
|             container.RegisterSingleton<IDmtpRouteService>(new DmtpRouteService() | ||||
|             { | ||||
|                 FindDmtpActor = func | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 添加基于设定委托的Dmtp路由服务。 | ||||
|         /// </summary> | ||||
|         /// <param name="container"></param> | ||||
|         /// <param name="action"></param> | ||||
|         public static void AddDmtpRouteService(this IContainer container, Func<string, IDmtpActor> action) | ||||
|         { | ||||
|             AddDmtpRouteService(container, async (id) => | ||||
|             { | ||||
|                 await EasyTask.CompletedTask; | ||||
|                 return action.Invoke(id); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -20,6 +20,6 @@ namespace ThingsGateway.Foundation.Dmtp | ||||
|         /// <summary> | ||||
|         /// 查找其他IDmtpActor | ||||
|         /// </summary> | ||||
|         Func<string, IDmtpActor> FindDmtpActor { get; set; } | ||||
|         Func<string, Task<IDmtpActor>> FindDmtpActor { get; set; } | ||||
|     } | ||||
| } | ||||
| @@ -374,7 +374,7 @@ namespace ThingsGateway.Foundation.Http | ||||
|         /// <returns></returns> | ||||
|         public static TResponse SetContentTypeFromFileName<TResponse>(this TResponse response, string fileName) where TResponse : HttpResponse | ||||
|         { | ||||
|             var contentDisposition = "attachment;" + "filename=" + System.Web.HttpUtility.UrlEncode(fileName); | ||||
|             var contentDisposition = $"attachment;filename={System.Web.HttpUtility.UrlEncode(fileName)}"; | ||||
|             response.Headers.Add(HttpHeaders.ContentDisposition, contentDisposition); | ||||
|             return response; | ||||
|         } | ||||
| @@ -429,7 +429,7 @@ namespace ThingsGateway.Foundation.Http | ||||
|             using (var reader = FilePool.GetReader(filePath)) | ||||
|             { | ||||
|                 response.SetContentTypeByExtension(Path.GetExtension(filePath)); | ||||
|                 var contentDisposition = "attachment;" + "filename=" + System.Web.HttpUtility.UrlEncode(fileName ?? Path.GetFileName(filePath)); | ||||
|                 var contentDisposition = $"attachment;filename={System.Web.HttpUtility.UrlEncode(fileName ?? Path.GetFileName(filePath))}"; | ||||
|                 response.Headers.Add(HttpHeaders.ContentDisposition, contentDisposition); | ||||
|                 response.Headers.Add(HttpHeaders.AcceptRanges, "bytes"); | ||||
|  | ||||
| @@ -526,7 +526,7 @@ namespace ThingsGateway.Foundation.Http | ||||
|             using (var reader = FilePool.GetReader(filePath)) | ||||
|             { | ||||
|                 context.Response.SetContentTypeByExtension(Path.GetExtension(filePath)); | ||||
|                 var contentDisposition = "attachment;" + "filename=" + System.Web.HttpUtility.UrlEncode(fileName ?? Path.GetFileName(filePath)); | ||||
|                 var contentDisposition = $"attachment;filename={System.Web.HttpUtility.UrlEncode(fileName ?? Path.GetFileName(filePath))}"; | ||||
|                 context.Response.Headers.Add(HttpHeaders.ContentDisposition, contentDisposition); | ||||
|                 context.Response.Headers.Add(HttpHeaders.AcceptRanges, "bytes"); | ||||
|  | ||||
|   | ||||
| @@ -37,6 +37,10 @@ namespace ThingsGateway.Foundation.Http | ||||
|         public HttpStaticPagePlugin() | ||||
|         { | ||||
|             this.FileCache = new FileCachePool(); | ||||
|             this.SetNavigateAction(request => | ||||
|             { | ||||
|                 return request.RelativeURL; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -81,15 +85,45 @@ namespace ThingsGateway.Foundation.Http | ||||
|             this.FileCache.Clear(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 重新导航 | ||||
|         /// </summary> | ||||
|         public Func<HttpRequest, Task<string>> NavigateAction { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 设定重新导航 | ||||
|         /// </summary> | ||||
|         /// <param name="func"></param> | ||||
|         /// <returns></returns> | ||||
|         public HttpStaticPagePlugin SetNavigateAction(Func<HttpRequest, Task<string>> func) | ||||
|         { | ||||
|             this.NavigateAction = func; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 设定重新导航 | ||||
|         /// </summary> | ||||
|         /// <param name="func"></param> | ||||
|         /// <returns></returns> | ||||
|         public HttpStaticPagePlugin SetNavigateAction(Func<HttpRequest, string> func) | ||||
|         { | ||||
|             this.NavigateAction = (request) => | ||||
|             { | ||||
|                 return Task.FromResult(func(request)); | ||||
|             }; | ||||
|             return this; | ||||
|         } | ||||
|         /// <inheritdoc/> | ||||
|         public async Task OnHttpRequest(IHttpSocketClient client, HttpContextEventArgs e) | ||||
|         { | ||||
|             if (this.FileCache.Find(e.Context.Request.RelativeURL, out var data)) | ||||
|             var url = await this.NavigateAction.Invoke(e.Context.Request); | ||||
|             if (this.FileCache.Find(url, out var data)) | ||||
|             { | ||||
|                 e.Context.Response.SetStatus(); | ||||
|                 if (this.ContentTypeProvider?.TryGetContentType(e.Context.Request.RelativeURL, out var result) != true) | ||||
|                 if (this.ContentTypeProvider?.TryGetContentType(url, out var result) != true) | ||||
|                 { | ||||
|                     result = HttpTools.GetContentTypeFromExtension(e.Context.Request.RelativeURL); | ||||
|                     result = HttpTools.GetContentTypeFromExtension(url); | ||||
|                 } | ||||
|                 e.Context.Response.ContentType = result; | ||||
|                 e.Context.Response.SetContentLength(data.Length) | ||||
|   | ||||
| @@ -72,7 +72,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets | ||||
|             { | ||||
|                 return new WebSocketReceiveResult(this.ComplateRead, null); | ||||
|             } | ||||
|             await this.m_resetEventForRead.WaitOneAsync(token); | ||||
|             await this.m_resetEventForRead.WaitOneAsync(token).ConfigureFalseAwait(); | ||||
|             return new WebSocketReceiveResult(this.ComplateRead, this.m_dataFrame); | ||||
|         } | ||||
| #if NET6_0_OR_GREATER | ||||
| @@ -82,7 +82,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets | ||||
|             { | ||||
|                 return new WebSocketReceiveResult(this.ComplateRead, null); | ||||
|             } | ||||
|             await this.m_resetEventForRead.WaitOneAsync(token); | ||||
|             await this.m_resetEventForRead.WaitOneAsync(token).ConfigureFalseAwait(); | ||||
|             return new WebSocketReceiveResult(this.ComplateRead, this.m_dataFrame); | ||||
|         } | ||||
| #endif | ||||
| @@ -146,7 +146,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets | ||||
|             { | ||||
|                 return true; | ||||
|             } | ||||
|             if (await this.m_resetEventForComplateRead.WaitOneAsync(TimeSpan.FromSeconds(10))) | ||||
|             if (await this.m_resetEventForComplateRead.WaitOneAsync(TimeSpan.FromSeconds(10)).ConfigureFalseAwait()) | ||||
|             { | ||||
|                 return true; | ||||
|             } | ||||
|   | ||||
| @@ -66,7 +66,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets | ||||
|                             args.Context.Response.Build(byteBlock); | ||||
|                             await client.DefaultSendAsync(byteBlock).ConfigureAwait(false); | ||||
|                         } | ||||
|                         await client.PluginsManager.RaiseAsync(nameof(IWebSocketHandshakedPlugin.OnWebSocketHandshaked), client, new HttpContextEventArgs(httpContext)) | ||||
|                         _ = client.PluginsManager.RaiseAsync(nameof(IWebSocketHandshakedPlugin.OnWebSocketHandshaked), client, new HttpContextEventArgs(httpContext)) | ||||
|                             .ConfigureAwait(false); | ||||
|                         return true; | ||||
|                     } | ||||
|   | ||||
| @@ -101,7 +101,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets | ||||
|                 if (await this.VerifyConnection.Invoke(client, e.Context)) | ||||
|                 { | ||||
|                     e.Handled = true; | ||||
|                     _ = client.SwitchProtocolToWebSocket(e.Context); | ||||
|                     await client.SwitchProtocolToWebSocket(e.Context); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
| namespace ThingsGateway.Foundation.Rpc | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 标识该接口将自动生成调用的扩展方法静态类 | ||||
|     /// 标识该接口将自动生成调用的代理类 | ||||
|     /// </summary> | ||||
|     [AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)] | ||||
|     public sealed class GeneratorRpcProxyAttribute : Attribute | ||||
| @@ -39,7 +39,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         public string Namespace { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 生成的类名,不要包含“I”,生成接口时会自动家。 | ||||
|         /// 生成的类名,不要包含“I”,生成接口时会自动添加。 | ||||
|         /// </summary> | ||||
|         public string ClassName { get; set; } | ||||
|  | ||||
| @@ -48,11 +48,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// </summary> | ||||
|         public CodeGeneratorFlag GeneratorFlag { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 函数标识 | ||||
|         /// </summary> | ||||
|         public MethodFlags MethodFlags { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 继承接口 | ||||
|         /// </summary> | ||||
|   | ||||
| @@ -39,7 +39,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// </summary> | ||||
|         public RpcAttribute() | ||||
|         { | ||||
|             this.MethodFlags = MethodFlags.None; | ||||
|             this.Exceptions.Add(typeof(TimeoutException), "调用超时"); | ||||
|             this.Exceptions.Add(typeof(RpcInvokeException), "Rpc调用异常"); | ||||
|             this.Exceptions.Add(typeof(Exception), "其他异常"); | ||||
| @@ -72,11 +71,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// </summary> | ||||
|         public string InvokeKey { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 函数标识 | ||||
|         /// </summary> | ||||
|         public MethodFlags MethodFlags { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 是否仅以函数名调用,当为True是,调用时仅需要传入方法名即可。 | ||||
|         /// </summary> | ||||
| @@ -122,25 +116,25 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|  | ||||
|                 codeString.Append("public static "); | ||||
|                 codeString.Append(this.GetReturn(methodInstance, false)); | ||||
|                 codeString.Append(" "); | ||||
|                 codeString.Append(' '); | ||||
|                 codeString.Append(this.GetMethodName(methodInstance, false)); | ||||
|                 codeString.Append("<TClient>(");//方法参数 | ||||
|  | ||||
|                 codeString.Append($"this TClient client"); | ||||
|  | ||||
|                 codeString.Append(","); | ||||
|                 codeString.Append(','); | ||||
|                 for (var i = 0; i < parametersStr.Count; i++) | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         codeString.Append(","); | ||||
|                         codeString.Append(','); | ||||
|                     } | ||||
|  | ||||
|                     codeString.Append(parametersStr[i]); | ||||
|                 } | ||||
|                 if (parametersStr.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append(","); | ||||
|                     codeString.Append(','); | ||||
|                 } | ||||
|                 codeString.Append(this.GetInvokeOption()); | ||||
|                 codeString.AppendLine(") where TClient:"); | ||||
| @@ -149,7 +143,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         codeString.Append(","); | ||||
|                         codeString.Append(','); | ||||
|                     } | ||||
|  | ||||
|                     codeString.Append(InterfaceTypes[i].FullName); | ||||
| @@ -159,7 +153,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 if (parametersStr.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append($"object[] parameters = new object[]"); | ||||
|                     codeString.Append("{"); | ||||
|                     codeString.Append('{'); | ||||
|  | ||||
|                     foreach (var parameter in parameters) | ||||
|                     { | ||||
| @@ -173,7 +167,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                         } | ||||
|                         if (parameter != parameters[parameters.Length - 1]) | ||||
|                         { | ||||
|                             codeString.Append(","); | ||||
|                             codeString.Append(','); | ||||
|                         } | ||||
|                     } | ||||
|                     codeString.AppendLine("};"); | ||||
| @@ -181,13 +175,13 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append($"Type[] types = new Type[]"); | ||||
|                         codeString.Append("{"); | ||||
|                         codeString.Append('{'); | ||||
|                         foreach (var parameter in parameters) | ||||
|                         { | ||||
|                             codeString.Append($"typeof({this.GetProxyParameterName(parameter)})"); | ||||
|                             if (parameter != parameters[parameters.Length - 1]) | ||||
|                             { | ||||
|                                 codeString.Append(","); | ||||
|                                 codeString.Append(','); | ||||
|                             } | ||||
|                         } | ||||
|                         codeString.AppendLine("};"); | ||||
| @@ -199,7 +193,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     if (parametersStr.Count == 0) | ||||
|                     { | ||||
|                         codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append("("); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, null);"); | ||||
| @@ -207,7 +201,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     else if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append("("); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption,ref parameters,types);"); | ||||
| @@ -215,7 +209,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     else | ||||
|                     { | ||||
|                         codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append("("); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, parameters);"); | ||||
| @@ -275,12 +269,12 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|             } | ||||
|  | ||||
|             //以下生成异步 | ||||
|             if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync) && !isOut && !isRef)//没有out或者ref | ||||
|             if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync) /*&& !isOut && !isRef*/) | ||||
|             { | ||||
|                 codeString.AppendLine("///<summary>"); | ||||
|                 codeString.AppendLine($"///{description}"); | ||||
|                 codeString.AppendLine("///</summary>"); | ||||
|                 if (methodInstance.HasReturn) | ||||
|                 if (methodInstance.HasReturn && !isOut && !isRef) | ||||
|                 { | ||||
|                     codeString.Append("public static async "); | ||||
|                 } | ||||
| @@ -289,24 +283,24 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     codeString.Append("public static "); | ||||
|                 } | ||||
|                 codeString.Append(this.GetReturn(methodInstance, true)); | ||||
|                 codeString.Append(" "); | ||||
|                 codeString.Append(' '); | ||||
|                 codeString.Append(this.GetMethodName(methodInstance, true)); | ||||
|                 codeString.Append("<TClient>(");//方法参数 | ||||
|  | ||||
|                 codeString.Append($"this TClient client"); | ||||
|  | ||||
|                 codeString.Append(","); | ||||
|                 codeString.Append(','); | ||||
|                 for (var i = 0; i < parametersStr.Count; i++) | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         codeString.Append(","); | ||||
|                         codeString.Append(','); | ||||
|                     } | ||||
|                     codeString.Append(parametersStr[i]); | ||||
|                 } | ||||
|                 if (parametersStr.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append(","); | ||||
|                     codeString.Append(','); | ||||
|                 } | ||||
|                 codeString.Append(this.GetInvokeOption()); | ||||
|                 codeString.AppendLine(") where TClient:"); | ||||
| @@ -315,7 +309,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         codeString.Append(","); | ||||
|                         codeString.Append(','); | ||||
|                     } | ||||
|  | ||||
|                     codeString.Append(InterfaceTypes[i].FullName); | ||||
| @@ -326,16 +320,39 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 if (parametersStr.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append($"object[] parameters = new object[]"); | ||||
|                     codeString.Append("{"); | ||||
|                     codeString.Append('{'); | ||||
|  | ||||
|                     foreach (var parameter in parameters) | ||||
|                     { | ||||
|                         codeString.Append(parameter.Name); | ||||
|                         if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut) | ||||
|                         { | ||||
|                             codeString.Append($"default({this.GetProxyParameterName(parameter)})"); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             codeString.Append(parameter.Name); | ||||
|                         } | ||||
|                         if (parameter != parameters[parameters.Length - 1]) | ||||
|                         { | ||||
|                             codeString.Append(","); | ||||
|                             codeString.Append(','); | ||||
|                         } | ||||
|                     } | ||||
|                     codeString.AppendLine("};"); | ||||
|  | ||||
|                     if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append($"Type[] types = new Type[]"); | ||||
|                         codeString.Append('{'); | ||||
|                         foreach (var parameter in parameters) | ||||
|                         { | ||||
|                             codeString.Append($"typeof({this.GetProxyParameterName(parameter)})"); | ||||
|                             if (parameter != parameters[parameters.Length - 1]) | ||||
|                             { | ||||
|                                 codeString.Append(','); | ||||
|                             } | ||||
|                         } | ||||
|                         codeString.AppendLine("};"); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (methodInstance.HasReturn) | ||||
| @@ -343,15 +360,23 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     if (parametersStr.Count == 0) | ||||
|                     { | ||||
|                         codeString.Append(string.Format("return ({0}) await client.InvokeAsync", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append("("); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, null);"); | ||||
|                     } | ||||
|                     else if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption,ref parameters,types);"); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         codeString.Append(string.Format("return ({0}) await client.InvokeAsync", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append("("); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, parameters);"); | ||||
| @@ -365,6 +390,12 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, null);"); | ||||
|                     } | ||||
|                     else if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append("client.Invoke("); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption,ref parameters,types);"); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         codeString.Append("return client.InvokeAsync("); | ||||
| @@ -372,6 +403,43 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                         codeString.AppendLine(",invokeOption, parameters);"); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (isOut || isRef) | ||||
|                 { | ||||
|                     codeString.AppendLine("if(parameters!=null)"); | ||||
|                     codeString.AppendLine("{"); | ||||
|                     for (var i = 0; i < parameters.Length; i++) | ||||
|                     { | ||||
|                         codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, this.GetProxyParameterName(parameters[i]), i)); | ||||
|                     } | ||||
|                     codeString.AppendLine("}"); | ||||
|                     if (isOut) | ||||
|                     { | ||||
|                         codeString.AppendLine("else"); | ||||
|                         codeString.AppendLine("{"); | ||||
|                         for (var i = 0; i < parameters.Length; i++) | ||||
|                         { | ||||
|                             if (parameters[i].IsOut) | ||||
|                             { | ||||
|                                 codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, this.GetProxyParameterName(parameters[i]))); | ||||
|                             } | ||||
|                         } | ||||
|                         codeString.AppendLine("}"); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (isOut || isRef) | ||||
|                 { | ||||
|                     if (methodInstance.HasReturn) | ||||
|                     { | ||||
|                         codeString.AppendLine(string.Format("return Task.FromResult<{0}>(returnData);", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         codeString.AppendLine(string.Format("return  EasyTask.CompletedTask;")); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 codeString.AppendLine("}"); | ||||
|             } | ||||
|             return codeString.ToString(); | ||||
| @@ -409,21 +477,21 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|  | ||||
|                 codeString.Append("public "); | ||||
|                 codeString.Append(this.GetReturn(methodInstance, false)); | ||||
|                 codeString.Append(" "); | ||||
|                 codeString.Append(' '); | ||||
|                 codeString.Append(this.GetMethodName(methodInstance, false)); | ||||
|                 codeString.Append("(");//方法参数 | ||||
|                 codeString.Append('(');//方法参数 | ||||
|  | ||||
|                 for (var i = 0; i < parametersStr.Count; i++) | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         codeString.Append(","); | ||||
|                         codeString.Append(','); | ||||
|                     } | ||||
|                     codeString.Append(parametersStr[i]); | ||||
|                 } | ||||
|                 if (parametersStr.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append(","); | ||||
|                     codeString.Append(','); | ||||
|                 } | ||||
|                 codeString.Append(this.GetInvokeOption()); | ||||
|                 codeString.AppendLine(")"); | ||||
| @@ -438,7 +506,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 if (parametersStr.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append($"object[] parameters = new object[]"); | ||||
|                     codeString.Append("{"); | ||||
|                     codeString.Append('{'); | ||||
|  | ||||
|                     foreach (var parameter in parameters) | ||||
|                     { | ||||
| @@ -452,7 +520,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                         } | ||||
|                         if (parameter != parameters[parameters.Length - 1]) | ||||
|                         { | ||||
|                             codeString.Append(","); | ||||
|                             codeString.Append(','); | ||||
|                         } | ||||
|                     } | ||||
|                     codeString.AppendLine("};"); | ||||
| @@ -460,13 +528,13 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append($"Type[] types = new Type[]"); | ||||
|                         codeString.Append("{"); | ||||
|                         codeString.Append('{'); | ||||
|                         foreach (var parameter in parameters) | ||||
|                         { | ||||
|                             codeString.Append($"typeof({this.GetProxyParameterName(parameter)})"); | ||||
|                             if (parameter != parameters[parameters.Length - 1]) | ||||
|                             { | ||||
|                                 codeString.Append(","); | ||||
|                                 codeString.Append(','); | ||||
|                             } | ||||
|                         } | ||||
|                         codeString.AppendLine("};"); | ||||
| @@ -478,7 +546,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     if (parametersStr.Count == 0) | ||||
|                     { | ||||
|                         codeString.Append(string.Format("{0} returnData=({0})Client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append("("); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, null);"); | ||||
| @@ -554,12 +622,12 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|             } | ||||
|  | ||||
|             //以下生成异步 | ||||
|             if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync) && !isOut && !isRef)//没有out或者ref | ||||
|             if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync)) | ||||
|             { | ||||
|                 codeString.AppendLine("///<summary>"); | ||||
|                 codeString.AppendLine($"///{description}"); | ||||
|                 codeString.AppendLine("///</summary>"); | ||||
|                 if (methodInstance.HasReturn) | ||||
|                 if (methodInstance.HasReturn && (!isOut && !isRef)) | ||||
|                 { | ||||
|                     codeString.Append("public async "); | ||||
|                 } | ||||
| @@ -568,21 +636,21 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     codeString.Append("public "); | ||||
|                 } | ||||
|                 codeString.Append(this.GetReturn(methodInstance, true)); | ||||
|                 codeString.Append(" "); | ||||
|                 codeString.Append(' '); | ||||
|                 codeString.Append(this.GetMethodName(methodInstance, true)); | ||||
|                 codeString.Append("(");//方法参数 | ||||
|                 codeString.Append('(');//方法参数 | ||||
|  | ||||
|                 for (var i = 0; i < parametersStr.Count; i++) | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         codeString.Append(","); | ||||
|                         codeString.Append(','); | ||||
|                     } | ||||
|                     codeString.Append(parametersStr[i]); | ||||
|                 } | ||||
|                 if (parametersStr.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append(","); | ||||
|                     codeString.Append(','); | ||||
|                 } | ||||
|                 codeString.Append(this.GetInvokeOption()); | ||||
|                 codeString.AppendLine(")"); | ||||
| @@ -597,16 +665,39 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 if (parametersStr.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append($"object[] parameters = new object[]"); | ||||
|                     codeString.Append("{"); | ||||
|                     codeString.Append('{'); | ||||
|  | ||||
|                     foreach (var parameter in parameters) | ||||
|                     { | ||||
|                         codeString.Append(parameter.Name); | ||||
|                         if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut) | ||||
|                         { | ||||
|                             codeString.Append($"default({this.GetProxyParameterName(parameter)})"); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             codeString.Append(parameter.Name); | ||||
|                         } | ||||
|                         if (parameter != parameters[parameters.Length - 1]) | ||||
|                         { | ||||
|                             codeString.Append(","); | ||||
|                             codeString.Append(','); | ||||
|                         } | ||||
|                     } | ||||
|                     codeString.AppendLine("};"); | ||||
|  | ||||
|                     if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append($"Type[] types = new Type[]"); | ||||
|                         codeString.Append('{'); | ||||
|                         foreach (var parameter in parameters) | ||||
|                         { | ||||
|                             codeString.Append($"typeof({this.GetProxyParameterName(parameter)})"); | ||||
|                             if (parameter != parameters[parameters.Length - 1]) | ||||
|                             { | ||||
|                                 codeString.Append(','); | ||||
|                             } | ||||
|                         } | ||||
|                         codeString.AppendLine("};"); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (methodInstance.HasReturn) | ||||
| @@ -614,15 +705,23 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     if (parametersStr.Count == 0) | ||||
|                     { | ||||
|                         codeString.Append(string.Format("return ({0}) await Client.InvokeAsync", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append("("); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, null);"); | ||||
|                     } | ||||
|                     else if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append(string.Format("{0} returnData=({0})Client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption,ref parameters,types);"); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         codeString.Append(string.Format("return ({0}) await Client.InvokeAsync", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append("("); | ||||
|                         codeString.Append('('); | ||||
|                         codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, parameters);"); | ||||
| @@ -636,6 +735,12 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption, null);"); | ||||
|                     } | ||||
|                     else if (isOut || isRef) | ||||
|                     { | ||||
|                         codeString.Append("Client.Invoke("); | ||||
|                         codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\""); | ||||
|                         codeString.AppendLine(",invokeOption,ref parameters,types);"); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         codeString.Append("return Client.InvokeAsync("); | ||||
| @@ -643,8 +748,46 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                         codeString.AppendLine(",invokeOption, parameters);"); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (isOut || isRef) | ||||
|                 { | ||||
|                     codeString.AppendLine("if(parameters!=null)"); | ||||
|                     codeString.AppendLine("{"); | ||||
|                     for (var i = 0; i < parameters.Length; i++) | ||||
|                     { | ||||
|                         codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, this.GetProxyParameterName(parameters[i]), i)); | ||||
|                     } | ||||
|                     codeString.AppendLine("}"); | ||||
|                     if (isOut) | ||||
|                     { | ||||
|                         codeString.AppendLine("else"); | ||||
|                         codeString.AppendLine("{"); | ||||
|                         for (var i = 0; i < parameters.Length; i++) | ||||
|                         { | ||||
|                             if (parameters[i].IsOut) | ||||
|                             { | ||||
|                                 codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, this.GetProxyParameterName(parameters[i]))); | ||||
|                             } | ||||
|                         } | ||||
|                         codeString.AppendLine("}"); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (isOut || isRef) | ||||
|                 { | ||||
|                     if (methodInstance.HasReturn) | ||||
|                     { | ||||
|                         codeString.AppendLine(string.Format("return Task.FromResult<{0}>(returnData);", this.GetProxyParameterName(methodInstance.Info.ReturnParameter))); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         codeString.AppendLine(string.Format("return  EasyTask.CompletedTask;")); | ||||
|                     } | ||||
|                 } | ||||
|                 codeString.AppendLine("}"); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             return codeString.ToString(); | ||||
|         } | ||||
|  | ||||
| @@ -669,26 +812,26 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 } | ||||
|  | ||||
|                 codeString.Append(this.GetReturn(methodInstance, false)); | ||||
|                 codeString.Append(" "); | ||||
|                 codeString.Append(' '); | ||||
|                 codeString.Append(this.GetMethodName(methodInstance, false)); | ||||
|                 codeString.Append("(");//方法参数 | ||||
|                 codeString.Append('(');//方法参数 | ||||
|                 for (var i = 0; i < parameters.Count; i++) | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         codeString.Append(","); | ||||
|                         codeString.Append(','); | ||||
|                     } | ||||
|                     codeString.Append(parameters[i]); | ||||
|                 } | ||||
|                 if (parameters.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append(","); | ||||
|                     codeString.Append(','); | ||||
|                 } | ||||
|                 codeString.Append(this.GetInvokeOption()); | ||||
|                 codeString.AppendLine(");"); | ||||
|             } | ||||
|  | ||||
|             if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync) && !isOut && !isRef)//没有out或者ref | ||||
|             if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync)) | ||||
|             { | ||||
|                 codeString.AppendLine("///<summary>"); | ||||
|                 codeString.AppendLine($"///{description}"); | ||||
| @@ -699,21 +842,21 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 } | ||||
|  | ||||
|                 codeString.Append(this.GetReturn(methodInstance, true)); | ||||
|                 codeString.Append(" "); | ||||
|                 codeString.Append(' '); | ||||
|                 codeString.Append(this.GetMethodName(methodInstance, true)); | ||||
|                 codeString.Append("(");//方法参数 | ||||
|                 codeString.Append('(');//方法参数 | ||||
|  | ||||
|                 for (var i = 0; i < parameters.Count; i++) | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         codeString.Append(","); | ||||
|                         codeString.Append(','); | ||||
|                     } | ||||
|                     codeString.Append(parameters[i]); | ||||
|                 } | ||||
|                 if (parameters.Count > 0) | ||||
|                 { | ||||
|                     codeString.Append(","); | ||||
|                     codeString.Append(','); | ||||
|                 } | ||||
|                 codeString.Append(this.GetInvokeOption()); | ||||
|                 codeString.AppendLine(");"); | ||||
| @@ -774,7 +917,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|             isOut = false; | ||||
|             isRef = false; | ||||
|  | ||||
|             if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext)) | ||||
|             if (methodInstance.IncludeCallContext) | ||||
|             { | ||||
|                 var infos = new List<ParameterInfo>(methodInstance.Parameters); | ||||
|                 infos.RemoveAt(0); | ||||
|   | ||||
| @@ -302,7 +302,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                         } | ||||
|  | ||||
|                         var i = 0; | ||||
|                         if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext)) | ||||
|                         if (methodInstance.IncludeCallContext) | ||||
|                         { | ||||
|                             i = 1; | ||||
|                         } | ||||
|   | ||||
| @@ -75,10 +75,10 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|             } | ||||
|  | ||||
|             var fromMethodInfos = new Dictionary<string, MethodInfo>(); | ||||
|             CodeGenerator.GetMethodInfos(ServerFromType, ref fromMethodInfos); | ||||
|             CodeGenerator.GetMethodInfos(this.ServerFromType, ref fromMethodInfos); | ||||
|  | ||||
|             var toMethodInfos = new Dictionary<string, MethodInfo>(); | ||||
|             CodeGenerator.GetMethodInfos(ServerToType, ref toMethodInfos); | ||||
|             CodeGenerator.GetMethodInfos(this.ServerToType, ref toMethodInfos); | ||||
|  | ||||
|             var attributes = method.GetCustomAttributes<RpcAttribute>(true); | ||||
|             if (attributes.Any()) | ||||
| @@ -98,7 +98,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 foreach (var item in ServerFromType.GetCustomAttributes(true)) | ||||
|                 foreach (var item in this.ServerFromType.GetCustomAttributes(true)) | ||||
|                 { | ||||
|                     if (item is IRpcActionFilter filter) | ||||
|                     { | ||||
| @@ -106,7 +106,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (ServerFromType != ServerToType) | ||||
|                 if (this.ServerFromType != this.ServerToType) | ||||
|                 { | ||||
|                     foreach (var item in toMethod.GetCustomAttributes(true)) | ||||
|                     { | ||||
| @@ -116,7 +116,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     foreach (var item in ServerToType.GetCustomAttributes(true)) | ||||
|                     foreach (var item in this.ServerToType.GetCustomAttributes(true)) | ||||
|                     { | ||||
|                         if (item is IRpcActionFilter filter) | ||||
|                         { | ||||
| @@ -128,17 +128,23 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|                 { | ||||
|                     this.Filters = actionFilters.ToArray(); | ||||
|                 } | ||||
|                 foreach (var item in attributes) | ||||
|                 //foreach (var item in attributes) | ||||
|                 //{ | ||||
|                 //    this.MethodFlags |= item.MethodFlags; | ||||
|                 //} | ||||
|                 //if (this.MethodFlags.HasFlag(MethodFlags.IncludeCallContext)) | ||||
|                 //{ | ||||
|                 //    if (this.Parameters.Length == 0 || !typeof(ICallContext).IsAssignableFrom(this.Parameters[0].ParameterType)) | ||||
|                 //    { | ||||
|                 //        throw new RpcException($"函数:{method},标识包含{MethodFlags.IncludeCallContext}时,必须包含{nameof(ICallContext)}或其派生类参数,且为第一参数。"); | ||||
|                 //    } | ||||
|                 //} | ||||
|  | ||||
|                 if (this.Parameters.Length > 0 && typeof(ICallContext).IsAssignableFrom(this.Parameters[0].ParameterType)) | ||||
|                 { | ||||
|                     this.MethodFlags |= item.MethodFlags; | ||||
|                 } | ||||
|                 if (this.MethodFlags.HasFlag(MethodFlags.IncludeCallContext)) | ||||
|                 { | ||||
|                     if (this.Parameters.Length == 0 || !typeof(ICallContext).IsAssignableFrom(this.Parameters[0].ParameterType)) | ||||
|                     { | ||||
|                         throw new RpcException($"函数:{method},标识包含{MethodFlags.IncludeCallContext}时,必须包含{nameof(ICallContext)}或其派生类参数,且为第一参数。"); | ||||
|                     } | ||||
|                     this.IncludeCallContext = true; | ||||
|                 } | ||||
|  | ||||
|                 var names = new List<string>(); | ||||
|                 foreach (var parameterInfo in this.Parameters) | ||||
|                 { | ||||
| @@ -155,6 +161,11 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 是否包含调用上下文 | ||||
|         /// </summary> | ||||
|         public bool IncludeCallContext { get; private set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 筛选器 | ||||
|         /// </summary> | ||||
| @@ -165,11 +176,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// </summary> | ||||
|         public bool IsEnable { get; set; } = true; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 函数标识 | ||||
|         /// </summary> | ||||
|         public MethodFlags MethodFlags { get; private set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 参数名集合 | ||||
|         /// </summary> | ||||
|   | ||||
| @@ -130,7 +130,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|             catch (TargetInvocationException ex) | ||||
|             { | ||||
|                 invokeResult.Status = InvokeStatus.InvocationException; | ||||
|                 invokeResult.Message = ex.InnerException != null ? "函数内部发生异常,信息:" + ex.InnerException.Message : "函数内部发生异常,信息:未知"; | ||||
|                 invokeResult.Message = ex.InnerException != null ? $"函数内部发生异常,信息:{ex.InnerException.Message}" : "函数内部发生异常,信息:未知"; | ||||
|                 if (callContext.MethodInstance.Filters != null) | ||||
|                 { | ||||
|                     for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++) | ||||
| @@ -223,7 +223,7 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|             catch (TargetInvocationException ex) | ||||
|             { | ||||
|                 invokeResult.Status = InvokeStatus.InvocationException; | ||||
|                 invokeResult.Message = ex.InnerException != null ? "函数内部发生异常,信息:" + ex.InnerException.Message : "函数内部发生异常,信息:未知"; | ||||
|                 invokeResult.Message = ex.InnerException != null ? $"函数内部发生异常,信息:{ex.InnerException.Message}" : "函数内部发生异常,信息:未知"; | ||||
|                 if (callContext.MethodInstance.Filters != null) | ||||
|                 { | ||||
|                     for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++) | ||||
|   | ||||
| @@ -1,44 +0,0 @@ | ||||
| #region copyright | ||||
| //------------------------------------------------------------------------------ | ||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||
| //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||
| //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||
| //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||
| //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||
| //  QQ群:605534569 | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| //  此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 | ||||
| //  源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 | ||||
| //  CSDN博客:https://blog.csdn.net/qq_40374647 | ||||
| //  哔哩哔哩视频:https://space.bilibili.com/94253567 | ||||
| //  Gitee源代码仓库:https://gitee.com/RRQM_Home | ||||
| //  Github源代码仓库:https://github.com/RRQM | ||||
| //  API首页:http://rrqm_home.gitee.io/touchsocket/ | ||||
| //  交流QQ群:234762506 | ||||
| //  感谢您的下载和使用 | ||||
| //------------------------------------------------------------------------------ | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Rpc | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 函数标识 | ||||
|     /// </summary> | ||||
|     [Flags] | ||||
|     public enum MethodFlags | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// 空 | ||||
|         /// </summary> | ||||
|         None = 1, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 包含调用上下文 | ||||
|         /// </summary> | ||||
|         IncludeCallContext = 2 | ||||
|     } | ||||
| } | ||||
| @@ -34,8 +34,8 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// 调用此服务的主体。 | ||||
|         /// <para> | ||||
|         /// <list type="bullet"> | ||||
|         /// <item>当该服务在<see cref="ITcpService"/>及派生中调用时,该值一般为<see cref="ISocketClient"/>对象。</item> | ||||
|         /// <item>当该服务在<see cref="ITcpClient"/>及派生中调用时,该值一般为<see cref="ITcpClient"/>对象。</item> | ||||
|         /// <item>当该服务在ITcpService及派生中调用时,该值一般为ISocketClient对象。</item> | ||||
|         /// <item>当该服务在ITcpClient及派生中调用时,该值一般为ITcpClient对象。</item> | ||||
|         /// </list> | ||||
|         /// </para> | ||||
|         /// </summary> | ||||
|   | ||||
| @@ -39,7 +39,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// <param name="parameters">参数</param> | ||||
|         /// <exception cref="TimeoutException">调用超时</exception> | ||||
|         /// <exception cref="RpcInvokeException">调用内部异常</exception> | ||||
|         /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception> | ||||
|         /// <exception cref="Exception">其他异常</exception> | ||||
|         Task InvokeAsync(string targetId, string invokeKey, IInvokeOption invokeOption, params object[] parameters); | ||||
|  | ||||
| @@ -53,7 +52,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// <param name="parameters">参数</param> | ||||
|         /// <exception cref="TimeoutException">调用超时</exception> | ||||
|         /// <exception cref="RpcInvokeException">调用内部异常</exception> | ||||
|         /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception> | ||||
|         /// <exception cref="Exception">其他异常</exception> | ||||
|         /// <returns>返回值</returns> | ||||
|         Task<object> InvokeAsync(Type returnType, string targetId, string invokeKey, IInvokeOption invokeOption, params object[] parameters); | ||||
| @@ -67,7 +65,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// <param name="parameters">参数</param> | ||||
|         /// <exception cref="TimeoutException">调用超时</exception> | ||||
|         /// <exception cref="RpcInvokeException">调用内部异常</exception> | ||||
|         /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception> | ||||
|         /// <exception cref="Exception">其他异常</exception> | ||||
|         void Invoke(string targetId, string invokeKey, IInvokeOption invokeOption, params object[] parameters); | ||||
|  | ||||
| @@ -81,7 +78,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// <param name="parameters">参数</param> | ||||
|         /// <exception cref="TimeoutException">调用超时</exception> | ||||
|         /// <exception cref="RpcInvokeException">调用内部异常</exception> | ||||
|         /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception> | ||||
|         /// <exception cref="Exception">其他异常</exception> | ||||
|         /// <returns>返回值</returns> | ||||
|         object Invoke(Type returnType, string targetId, string invokeKey, IInvokeOption invokeOption, params object[] parameters); | ||||
| @@ -96,7 +92,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// <param name="types"></param> | ||||
|         /// <exception cref="TimeoutException">调用超时</exception> | ||||
|         /// <exception cref="RpcInvokeException">调用内部异常</exception> | ||||
|         /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception> | ||||
|         /// <exception cref="Exception">其他异常</exception> | ||||
|         void Invoke(string targetId, string invokeKey, IInvokeOption invokeOption, ref object[] parameters, Type[] types); | ||||
|  | ||||
| @@ -111,7 +106,6 @@ namespace ThingsGateway.Foundation.Rpc | ||||
|         /// <param name="types"></param> | ||||
|         /// <exception cref="TimeoutException">调用超时</exception> | ||||
|         /// <exception cref="RpcInvokeException">调用内部异常</exception> | ||||
|         /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception> | ||||
|         /// <exception cref="Exception">其他异常</exception> | ||||
|         /// <returns>返回值</returns> | ||||
|         object Invoke(Type returnType, string targetId, string invokeKey, IInvokeOption invokeOption, ref object[] parameters, Type[] types); | ||||
|   | ||||
| @@ -21,22 +21,12 @@ public abstract class BaseSerial : DependencyObject, ISerial | ||||
|     /// 同步根。 | ||||
|     /// </summary> | ||||
|     protected readonly object SyncRoot = new object(); | ||||
|     private int m_receiveBufferSize = 1024 * 10; | ||||
|     private int m_sendBufferSize = 1024 * 10; | ||||
| 
 | ||||
|     /// <inheritdoc/> | ||||
|     public virtual int SendBufferSize | ||||
|     { | ||||
|         get => this.m_sendBufferSize; | ||||
|         set => this.m_sendBufferSize = value < 1024 ? 1024 : value; | ||||
|     } | ||||
|     public abstract int SendBufferSize { get; } | ||||
| 
 | ||||
|     /// <inheritdoc/> | ||||
|     public virtual int ReceiveBufferSize | ||||
|     { | ||||
|         get => this.m_receiveBufferSize; | ||||
|         set => this.m_receiveBufferSize = value < 1024 ? 1024 : value; | ||||
|     } | ||||
|     public abstract int ReceiveBufferSize { get; } | ||||
| 
 | ||||
|     /// <inheritdoc/> | ||||
|     public ILog Logger { get; set; } | ||||
| @@ -10,7 +10,6 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| using System.Diagnostics; | ||||
| using System.IO.Ports; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Serial; | ||||
| @@ -24,9 +23,14 @@ internal sealed class InternalSerialCore : SerialCore | ||||
| public class SerialCore : IDisposable, ISender | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 初始缓存大小 | ||||
|     /// 最小缓存尺寸 | ||||
|     /// </summary> | ||||
|     public const int BufferSize = 1024 * 10; | ||||
|     public int MinBufferSize { get; set; } = 1024 * 10; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 最大缓存尺寸 | ||||
|     /// </summary> | ||||
|     public int MaxBufferSize { get; set; } = 1024 * 1024 * 10; | ||||
|     #region 字段 | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -35,14 +39,14 @@ public class SerialCore : IDisposable, ISender | ||||
|     public readonly object SyncRoot = new object(); | ||||
|  | ||||
|     private long m_bufferRate; | ||||
|     private bool m_disposedValue; | ||||
|     private SpinLock m_lock; | ||||
|     private bool m_online => MainSerialPort?.IsOpen == true; | ||||
|     private int m_receiveBufferSize = BufferSize; | ||||
|     private bool m_online => m_serialPort?.IsOpen == true; | ||||
|     private int m_receiveBufferSize = 1024 * 10; | ||||
|     private ValueCounter m_receiveCounter; | ||||
|     private int m_sendBufferSize = BufferSize; | ||||
|     private int m_sendBufferSize = 1024 * 10; | ||||
|     private ValueCounter m_sendCounter; | ||||
|     private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); | ||||
|     private readonly EasyLock m_semaphoreForSend = new EasyLock(); | ||||
|     private SerialPort m_serialPort; | ||||
|  | ||||
|     #endregion 字段 | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -50,7 +54,6 @@ public class SerialCore : IDisposable, ISender | ||||
|     /// </summary> | ||||
|     public SerialCore() | ||||
|     { | ||||
|         this.m_lock = new SpinLock(Debugger.IsAttached); | ||||
|         this.m_receiveCounter = new ValueCounter | ||||
|         { | ||||
|             Period = TimeSpan.FromSeconds(1), | ||||
| @@ -69,7 +72,7 @@ public class SerialCore : IDisposable, ISender | ||||
|     /// </summary> | ||||
|     ~SerialCore() | ||||
|     { | ||||
|         this.Dispose(disposing: false); | ||||
|         this.SafeDispose(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
| @@ -100,19 +103,11 @@ public class SerialCore : IDisposable, ISender | ||||
|     public Action<SerialCore, ByteBlock> OnReceived { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 接收缓存池(可以设定初始值,运行时的值会根据流速自动调整) | ||||
|     /// 接收缓存池,运行时的值会根据流速自动调整 | ||||
|     /// </summary> | ||||
|     public int ReceiveBufferSize | ||||
|     { | ||||
|         get => this.m_receiveBufferSize; | ||||
|         set | ||||
|         { | ||||
|             this.m_receiveBufferSize = value; | ||||
|             if (this.MainSerialPort != null && !MainSerialPort.IsOpen) | ||||
|             { | ||||
|                 this.MainSerialPort.ReadBufferSize = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -121,19 +116,11 @@ public class SerialCore : IDisposable, ISender | ||||
|     public ValueCounter ReceiveCounter { get => this.m_receiveCounter; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 发送缓存池(可以设定初始值,运行时的值会根据流速自动调整) | ||||
|     /// 发送缓存池,运行时的值会根据流速自动调整 | ||||
|     /// </summary> | ||||
|     public int SendBufferSize | ||||
|     { | ||||
|         get => this.m_sendBufferSize; | ||||
|         set | ||||
|         { | ||||
|             this.m_sendBufferSize = value; | ||||
|             if (this.MainSerialPort != null && !MainSerialPort.IsOpen) | ||||
|             { | ||||
|                 this.MainSerialPort.WriteBufferSize = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -144,7 +131,7 @@ public class SerialCore : IDisposable, ISender | ||||
|     /// <summary> | ||||
|     /// SerialPort | ||||
|     /// </summary> | ||||
|     public SerialPort MainSerialPort { get; private set; } | ||||
|     public SerialPort MainSerialPort { get => this.m_serialPort; } | ||||
|  | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -155,11 +142,12 @@ public class SerialCore : IDisposable, ISender | ||||
|         var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize); | ||||
|         this.UserToken = byteBlock; | ||||
|         byteBlock.SetLength(0); | ||||
|         if (this.MainSerialPort.BytesToRead > 0) | ||||
|         if (this.m_serialPort.BytesToRead > 0) | ||||
|         { | ||||
|             this.m_bufferRate += 2; | ||||
|             this.ProcessReceived(); | ||||
|         } | ||||
|         MainSerialPort.DataReceived += MainSerialPort_DataReceived; | ||||
|         m_serialPort.DataReceived += MainSerialPort_DataReceived; | ||||
|     } | ||||
|  | ||||
|     private void MainSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) | ||||
| @@ -171,7 +159,7 @@ public class SerialCore : IDisposable, ISender | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             this.PrivateBreakOut(false, ex.Message); | ||||
|             this.PrivateBreakOut(false, ex.ToString()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -189,12 +177,12 @@ public class SerialCore : IDisposable, ISender | ||||
|     /// </summary> | ||||
|     public void Dispose() | ||||
|     { | ||||
|         this.Dispose(disposing: true); | ||||
|         GC.SuppressFinalize(this); | ||||
|         UserToken.SafeDispose(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 重置环境,并设置新的<see cref="MainSerialPort"/>。 | ||||
|     /// 重置环境,并设置新的<see cref="m_serialPort"/>。 | ||||
|     /// </summary> | ||||
|     /// <param name="socket"></param> | ||||
|     public virtual void Reset(SerialPort socket) | ||||
| @@ -209,7 +197,7 @@ public class SerialCore : IDisposable, ISender | ||||
|             throw new Exception("新的SerialPort必须在连接状态。"); | ||||
|         } | ||||
|         this.Reset(); | ||||
|         this.MainSerialPort = socket; | ||||
|         this.m_serialPort = socket; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -219,14 +207,24 @@ public class SerialCore : IDisposable, ISender | ||||
|     { | ||||
|         this.m_receiveCounter.Reset(); | ||||
|         this.m_sendCounter.Reset(); | ||||
|         this.MainSerialPort = null; | ||||
|         this.m_serialPort = null; | ||||
|         this.OnReceived = null; | ||||
|         this.OnBreakOut = null; | ||||
|         this.UserToken = null; | ||||
|         this.m_bufferRate = 1; | ||||
|         this.m_lock = new SpinLock(); | ||||
|         this.m_receiveBufferSize = BufferSize; | ||||
|         this.m_sendBufferSize = BufferSize; | ||||
|         this.m_receiveBufferSize = this.MinBufferSize; | ||||
|         this.m_sendBufferSize = this.MinBufferSize; | ||||
|     } | ||||
|     /// <summary> | ||||
|     /// 判断,当不在连接状态时触发异常。 | ||||
|     /// </summary> | ||||
|     /// <exception cref="NotConnectedException"></exception> | ||||
|     protected void ThrowIfNotConnected() | ||||
|     { | ||||
|         if (!this.m_online) | ||||
|         { | ||||
|             throw new NotConnectedException(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -240,15 +238,15 @@ public class SerialCore : IDisposable, ISender | ||||
|     /// <param name="length"></param> | ||||
|     public virtual void Send(byte[] buffer, int offset, int length) | ||||
|     { | ||||
|         var lockTaken = false; | ||||
|         this.ThrowIfNotConnected(); | ||||
|         try | ||||
|         { | ||||
|             this.m_lock.Enter(ref lockTaken); | ||||
|             this.MainSerialPort.Write(buffer, offset, length); | ||||
|             this.m_semaphoreForSend.Wait(); | ||||
|             this.m_serialPort.Write(buffer, offset, length); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             if (lockTaken) this.m_lock.Exit(false); | ||||
|             this.m_semaphoreForSend.Release(); | ||||
|         } | ||||
|         this.m_sendCounter.Increment(length); | ||||
|     } | ||||
| @@ -263,15 +261,16 @@ public class SerialCore : IDisposable, ISender | ||||
|     /// <exception cref="Exception"></exception> | ||||
|     public virtual async Task SendAsync(byte[] buffer, int offset, int length) | ||||
|     { | ||||
|         this.ThrowIfNotConnected(); | ||||
|         try | ||||
|         { | ||||
|             await this.m_semaphore.WaitAsync(); | ||||
|             await this.m_semaphoreForSend.WaitAsync(); | ||||
|  | ||||
|             this.MainSerialPort.Write(buffer, offset, length); | ||||
|             this.m_serialPort.Write(buffer, offset, length); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             this.m_semaphore.Release(); | ||||
|             this.m_semaphoreForSend.Release(); | ||||
|         } | ||||
|  | ||||
|         this.m_sendCounter.Increment(length); | ||||
| @@ -287,22 +286,7 @@ public class SerialCore : IDisposable, ISender | ||||
|         this.OnBreakOut?.Invoke(this, manual, msg); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 释放对象 | ||||
|     /// </summary> | ||||
|     /// <param name="disposing"></param> | ||||
|     protected virtual void Dispose(bool disposing) | ||||
|     { | ||||
|         if (!this.m_disposedValue) | ||||
|         { | ||||
|             if (disposing) | ||||
|             { | ||||
|             } | ||||
|  | ||||
|             this.m_disposedValue = true; | ||||
|         } | ||||
|         UserToken.SafeDispose(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 当发生异常的时候 | ||||
| @@ -341,12 +325,20 @@ public class SerialCore : IDisposable, ISender | ||||
|  | ||||
|     private void OnReceivePeriod(long value) | ||||
|     { | ||||
|         this.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value); | ||||
|         this.m_receiveBufferSize = Math.Max(TouchSocketUtility.HitBufferLength(value), this.MinBufferSize); | ||||
|         if (this.MainSerialPort != null && !MainSerialPort.IsOpen) | ||||
|         { | ||||
|             this.MainSerialPort.ReadBufferSize = this.m_receiveBufferSize; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void OnSendPeriod(long value) | ||||
|     { | ||||
|         this.SendBufferSize = TouchSocketUtility.HitBufferLength(value); | ||||
|         this.m_sendBufferSize = Math.Max(TouchSocketUtility.HitBufferLength(value), this.MinBufferSize); | ||||
|         if (this.MainSerialPort != null && !MainSerialPort.IsOpen) | ||||
|         { | ||||
|             this.MainSerialPort.WriteBufferSize = this.m_sendBufferSize; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void PrivateBreakOut(bool manual, string msg) | ||||
| @@ -367,21 +359,21 @@ public class SerialCore : IDisposable, ISender | ||||
|             UserToken?.SafeDispose(); | ||||
|             return; | ||||
|         } | ||||
|         if (MainSerialPort.BytesToRead > 0) | ||||
|         if (m_serialPort.BytesToRead > 0) | ||||
|         { | ||||
|             var byteBlock = UserToken; | ||||
|             byte[] buffer = BytePool.Default.Rent(MainSerialPort.BytesToRead); | ||||
|             int num = MainSerialPort.Read(buffer, 0, MainSerialPort.BytesToRead); | ||||
|             byte[] buffer = BytePool.Default.Rent(m_serialPort.BytesToRead); | ||||
|             int num = m_serialPort.Read(buffer, 0, m_serialPort.BytesToRead); | ||||
|             byteBlock.Write(buffer, 0, num); | ||||
|             byteBlock.SetLength(num); | ||||
|             this.HandleBuffer(byteBlock); | ||||
|             try | ||||
|             { | ||||
|                 var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength)); | ||||
|                 var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, this.MaxBufferSize)); | ||||
|                 newByteBlock.SetLength(0); | ||||
|                 UserToken = newByteBlock; | ||||
|  | ||||
|                 if (MainSerialPort.BytesToRead > 0) | ||||
|                 if (m_serialPort.BytesToRead > 0) | ||||
|                 { | ||||
|                     this.m_bufferRate += 2; | ||||
|                     this.ProcessReceived(); | ||||
| @@ -389,7 +381,7 @@ public class SerialCore : IDisposable, ISender | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 this.PrivateBreakOut(false, ex.Message); | ||||
|                 this.PrivateBreakOut(false, ex.ToString()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -57,7 +57,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|  | ||||
|     private DelaySender m_delaySender; | ||||
|     private bool m_online => MainSerialPort?.IsOpen == true; | ||||
|     private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); | ||||
|     private readonly EasyLock m_semaphore = new(); | ||||
|     private readonly InternalSerialCore m_serialCore; | ||||
|     #endregion 变量 | ||||
|  | ||||
| @@ -204,10 +204,10 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|     #region 属性 | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public DateTime LastReceivedTime => this.GetTcpCore().ReceiveCounter.LastIncrement; | ||||
|     public DateTime LastReceivedTime => this.GetSerialCore().ReceiveCounter.LastIncrement; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public DateTime LastSendTime => this.GetTcpCore().SendCounter.LastIncrement; | ||||
|     public DateTime LastSendTime => this.GetSerialCore().SendCounter.LastIncrement; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public IContainer Container { get; private set; } | ||||
| @@ -255,7 +255,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|             { | ||||
|                 Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, msg)); | ||||
|                 this.MainSerialPort.TryClose(); | ||||
|                 this.BreakOut(default, true, msg); | ||||
|                 this.BreakOut(true, msg); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -272,7 +272,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|             if (this.m_online) | ||||
|             { | ||||
|                 Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开")); | ||||
|                 this.BreakOut(default, true, $"{nameof(Dispose)}主动断开"); | ||||
|                 this.BreakOut(true, $"{nameof(Dispose)}主动断开"); | ||||
|             } | ||||
|         } | ||||
|         base.Dispose(disposing); | ||||
| @@ -321,7 +321,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|  | ||||
|     private void BeginReceive() | ||||
|     { | ||||
|         this.GetTcpCore().BeginIocpReceive(); | ||||
|         this.GetSerialCore().BeginIocpReceive(); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -361,7 +361,16 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|  | ||||
|     #endregion | ||||
|  | ||||
|     private void BreakOut(SerialCore core, bool manual, string msg) | ||||
|     private void SerialCoreBreakOut(SerialCore core, bool manual, string msg) | ||||
|     { | ||||
|         this.BreakOut(manual, msg); | ||||
|     } | ||||
|     /// <summary> | ||||
|     /// BreakOut。 | ||||
|     /// </summary> | ||||
|     /// <param name="manual"></param> | ||||
|     /// <param name="msg"></param> | ||||
|     protected void BreakOut(bool manual, string msg) | ||||
|     { | ||||
|         lock (this.SyncRoot) | ||||
|         { | ||||
| @@ -375,32 +384,22 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private SerialCore GetTcpCore() | ||||
|     private SerialCore GetSerialCore() | ||||
|     { | ||||
|         this.ThrowIfDisposed(); | ||||
|         return this.m_serialCore ?? throw new ObjectDisposedException(this.GetType().Name); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public override int ReceiveBufferSize | ||||
|     { | ||||
|         get => this.GetTcpCore().ReceiveBufferSize; | ||||
|         set | ||||
|         { | ||||
|             this.GetTcpCore().ReceiveBufferSize = value; | ||||
|         } | ||||
|         get => this.GetSerialCore().ReceiveBufferSize; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public override int SendBufferSize | ||||
|     { | ||||
|         get => this.GetTcpCore().SendBufferSize; | ||||
|         set | ||||
|         { | ||||
|             this.GetTcpCore().SendBufferSize = value; | ||||
|         } | ||||
|         get => this.GetSerialCore().SendBufferSize; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
| @@ -728,7 +727,12 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|     { | ||||
|         if (this.SendingData(buffer, offset, length).GetFalseAwaitResult()) | ||||
|         { | ||||
|             this.GetTcpCore().Send(buffer, offset, length); | ||||
|             if (this.m_delaySender != null) | ||||
|             { | ||||
|                 this.m_delaySender.Send(new QueueDataBytes(buffer, offset, length)); | ||||
|                 return; | ||||
|             } | ||||
|             this.GetSerialCore().Send(buffer, offset, length); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -737,7 +741,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|     { | ||||
|         if (await this.SendingData(buffer, offset, length)) | ||||
|         { | ||||
|             await this.GetTcpCore().SendAsync(buffer, offset, length); | ||||
|             await this.GetSerialCore().SendAsync(buffer, offset, length); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -769,8 +773,16 @@ public class SerialSessionBase : BaseSerial, ISerialSession | ||||
|         } | ||||
|         this.m_serialCore.Reset(serialPort); | ||||
|         this.m_serialCore.OnReceived = this.HandleReceived; | ||||
|         this.m_serialCore.OnBreakOut = this.BreakOut; | ||||
|         this.m_serialCore.OnBreakOut = this.SerialCoreBreakOut; | ||||
|         if (this.Config.GetValue(TouchSocketConfigExtension.MinBufferSizeProperty) is int minValue) | ||||
|         { | ||||
|             this.m_serialCore.MinBufferSize = minValue; | ||||
|         } | ||||
|  | ||||
|         if (this.Config.GetValue(TouchSocketConfigExtension.MaxBufferSizeProperty) is int maxValue) | ||||
|         { | ||||
|             this.m_serialCore.MaxBufferSize = maxValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void HandleReceived(SerialCore core, ByteBlock byteBlock) | ||||
|   | ||||
| @@ -35,22 +35,11 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|         /// </summary> | ||||
|         protected readonly object SyncRoot = new object(); | ||||
|  | ||||
|         private int m_receiveBufferSize = 1024 * 10; | ||||
|         private int m_sendBufferSize = 1024 * 10; | ||||
|         /// <inheritdoc/> | ||||
|         public abstract int SendBufferSize { get; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual int SendBufferSize | ||||
|         { | ||||
|             get => this.m_sendBufferSize; | ||||
|             set => this.m_sendBufferSize = value < 1024 ? 1024 : value; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public virtual int ReceiveBufferSize | ||||
|         { | ||||
|             get => this.m_receiveBufferSize; | ||||
|             set => this.m_receiveBufferSize = value < 1024 ? 1024 : value; | ||||
|         } | ||||
|         public abstract int ReceiveBufferSize { get; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public ILog Logger { get; set; } | ||||
|   | ||||
| @@ -51,6 +51,10 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|         /// </summary> | ||||
|         public int DelayLength { get; private set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 队列长度 | ||||
|         /// </summary> | ||||
|         public int QueueCount => this.m_queueDatas.Count; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 发送 | ||||
|   | ||||
| @@ -108,10 +108,6 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 最大BufferLength | ||||
|         /// </summary> | ||||
|         public static int MaxBufferLength { get; set; } = 1024 * 1024 * 10; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 命中BufferLength | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| using System.Diagnostics; | ||||
| using System.Net.Security; | ||||
| using System.Net.Sockets; | ||||
|  | ||||
| @@ -24,9 +23,15 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     private const string m_msg1 = "远程终端主动关闭"; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 初始缓存大小 | ||||
|     /// 最小缓存尺寸 | ||||
|     /// </summary> | ||||
|     public const int BufferSize = 1024 * 10; | ||||
|     public int MinBufferSize { get; set; } = 1024 * 10; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 最大缓存尺寸 | ||||
|     /// </summary> | ||||
|     public int MaxBufferSize { get; set; } = 1024 * 1024 * 10; | ||||
|  | ||||
|     #region 字段 | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -35,14 +40,13 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     public readonly object SyncRoot = new object(); | ||||
|  | ||||
|     private long m_bufferRate; | ||||
|     private bool m_disposedValue; | ||||
|     private SpinLock m_lock; | ||||
|     private volatile bool m_online; | ||||
|     private int m_receiveBufferSize = BufferSize; | ||||
|     private int m_receiveBufferSize = 1024 * 10; | ||||
|     private ValueCounter m_receiveCounter; | ||||
|     private int m_sendBufferSize = BufferSize; | ||||
|     private int m_sendBufferSize = 1024 * 10; | ||||
|     private ValueCounter m_sendCounter; | ||||
|     private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); | ||||
|     private Socket m_socket; | ||||
|     private readonly EasyLock m_semaphoreForSend = new(); | ||||
|     #endregion 字段 | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -50,7 +54,6 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     /// </summary> | ||||
|     public TcpCore() | ||||
|     { | ||||
|         this.m_lock = new SpinLock(Debugger.IsAttached); | ||||
|         this.m_receiveCounter = new ValueCounter | ||||
|         { | ||||
|             Period = TimeSpan.FromSeconds(1), | ||||
| @@ -64,14 +67,6 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 析构函数 | ||||
|     /// </summary> | ||||
|     ~TcpCore() | ||||
|     { | ||||
|         this.Dispose(disposing: false); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool CanSend => this.m_online; | ||||
|  | ||||
| @@ -96,16 +91,11 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     public Action<TcpCore, ByteBlock> OnReceived { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 接收缓存池(可以设定初始值,运行时的值会根据流速自动调整) | ||||
|     /// 接收缓存池,运行时的值会根据流速自动调整 | ||||
|     /// </summary> | ||||
|     public int ReceiveBufferSize | ||||
|     { | ||||
|         get => this.m_receiveBufferSize; | ||||
|         set | ||||
|         { | ||||
|             this.m_receiveBufferSize = value; | ||||
|             this.Socket.ReceiveBufferSize = value; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -114,16 +104,11 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     public ValueCounter ReceiveCounter { get => this.m_receiveCounter; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 发送缓存池(可以设定初始值,运行时的值会根据流速自动调整) | ||||
|     /// 发送缓存池,运行时的值会根据流速自动调整 | ||||
|     /// </summary> | ||||
|     public int SendBufferSize | ||||
|     { | ||||
|         get => this.m_sendBufferSize; | ||||
|         set | ||||
|         { | ||||
|             this.m_sendBufferSize = value; | ||||
|             this.Socket.SendBufferSize = value; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -134,7 +119,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     /// <summary> | ||||
|     /// Socket | ||||
|     /// </summary> | ||||
|     public Socket Socket { get; private set; } | ||||
|     public Socket Socket { get => this.m_socket; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 提供一个用于客户端-服务器通信的流,该流使用安全套接字层 (SSL) 安全协议对服务器和(可选)客户端进行身份验证。 | ||||
| @@ -152,7 +137,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     /// <param name="sslOption"></param> | ||||
|     public virtual void Authenticate(ServiceSslOption sslOption) | ||||
|     { | ||||
|         var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.Socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.Socket, false), false); | ||||
|         var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.m_socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.m_socket, false), false); | ||||
|         sslStream.AuthenticateAsServer(sslOption.Certificate); | ||||
|  | ||||
|         this.SslStream = sslStream; | ||||
| @@ -165,7 +150,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     /// <param name="sslOption"></param> | ||||
|     public virtual void Authenticate(ClientSslOption sslOption) | ||||
|     { | ||||
|         var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.Socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.Socket, false), false); | ||||
|         var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.m_socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.m_socket, false), false); | ||||
|         if (sslOption.ClientCertificates == null) | ||||
|         { | ||||
|             sslStream.AuthenticateAsClient(sslOption.TargetHost); | ||||
| @@ -185,7 +170,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     /// <returns></returns> | ||||
|     public virtual async Task AuthenticateAsync(ServiceSslOption sslOption) | ||||
|     { | ||||
|         var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.Socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.Socket, false), false); | ||||
|         var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.m_socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.m_socket, false), false); | ||||
|         await sslStream.AuthenticateAsServerAsync(sslOption.Certificate); | ||||
|  | ||||
|         this.SslStream = sslStream; | ||||
| @@ -199,7 +184,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     /// <returns></returns> | ||||
|     public virtual async Task AuthenticateAsync(ClientSslOption sslOption) | ||||
|     { | ||||
|         var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.Socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.Socket, false), false); | ||||
|         var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.m_socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.m_socket, false), false); | ||||
|         if (sslOption.ClientCertificates == null) | ||||
|         { | ||||
|             await sslStream.AuthenticateAsClientAsync(sslOption.TargetHost); | ||||
| @@ -220,8 +205,9 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|         var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize); | ||||
|         this.UserToken = byteBlock; | ||||
|         this.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity); | ||||
|         if (!this.Socket.ReceiveAsync(this)) | ||||
|         if (!this.m_socket.ReceiveAsync(this)) | ||||
|         { | ||||
|             this.m_bufferRate += 2; | ||||
|             this.ProcessReceived(this); | ||||
|         } | ||||
|     } | ||||
| @@ -257,7 +243,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 byteBlock.Dispose(); | ||||
|                 this.PrivateBreakOut(false, ex.Message); | ||||
|                 this.PrivateBreakOut(false, ex.ToString()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -271,15 +257,6 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|         this.PrivateBreakOut(true, msg); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 释放对象 | ||||
|     /// </summary> | ||||
|     public new void Dispose() | ||||
|     { | ||||
|         // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中 | ||||
|         this.Dispose(disposing: true); | ||||
|         GC.SuppressFinalize(this); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 重置环境,并设置新的<see cref="Socket"/>。 | ||||
| @@ -298,7 +275,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|         } | ||||
|         this.Reset(); | ||||
|         this.m_online = true; | ||||
|         this.Socket = socket; | ||||
|         this.m_socket = socket; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -310,17 +287,26 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|         this.m_sendCounter.Reset(); | ||||
|         this.SslStream?.Dispose(); | ||||
|         this.SslStream = null; | ||||
|         this.Socket = null; | ||||
|         this.m_socket = null; | ||||
|         this.OnReceived = null; | ||||
|         this.OnBreakOut = null; | ||||
|         this.UserToken = null; | ||||
|         this.m_bufferRate = 1; | ||||
|         this.m_lock = new SpinLock(); | ||||
|         this.m_receiveBufferSize = BufferSize; | ||||
|         this.m_sendBufferSize = BufferSize; | ||||
|         this.m_receiveBufferSize = this.MinBufferSize; | ||||
|         this.m_sendBufferSize = this.MinBufferSize; | ||||
|         this.m_online = false; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 判断,当不在连接状态时触发异常。 | ||||
|     /// </summary> | ||||
|     /// <exception cref="NotConnectedException"></exception> | ||||
|     protected void ThrowIfNotConnected() | ||||
|     { | ||||
|         if (!this.m_online) | ||||
|         { | ||||
|             throw new NotConnectedException(); | ||||
|         } | ||||
|     } | ||||
|     /// <summary> | ||||
|     /// 发送数据。 | ||||
|     /// <para> | ||||
| @@ -332,19 +318,19 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     /// <param name="length"></param> | ||||
|     public virtual void Send(byte[] buffer, int offset, int length) | ||||
|     { | ||||
|         this.ThrowIfNotConnected(); | ||||
|         if (this.UseSsl) | ||||
|         { | ||||
|             this.SslStream.Write(buffer, offset, length); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             var lockTaken = false; | ||||
|             try | ||||
|             { | ||||
|                 this.m_lock.Enter(ref lockTaken); | ||||
|                 this.m_semaphoreForSend.Wait(); | ||||
|                 while (length > 0) | ||||
|                 { | ||||
|                     var r = this.Socket.Send(buffer, offset, length, SocketFlags.None); | ||||
|                     var r = this.m_socket.Send(buffer, offset, length, SocketFlags.None); | ||||
|                     if (r == 0 && length > 0) | ||||
|                     { | ||||
|                         throw new Exception("发送数据不完全"); | ||||
| @@ -355,7 +341,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 if (lockTaken) this.m_lock.Exit(false); | ||||
|                 this.m_semaphoreForSend.Release(); | ||||
|             } | ||||
|         } | ||||
|         this.m_sendCounter.Increment(length); | ||||
| @@ -374,6 +360,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|     /// <exception cref="Exception"></exception> | ||||
|     public virtual async Task SendAsync(byte[] buffer, int offset, int length) | ||||
|     { | ||||
|         this.ThrowIfNotConnected(); | ||||
| #if NET6_0_OR_GREATER | ||||
|         if (this.UseSsl) | ||||
|         { | ||||
| @@ -383,11 +370,11 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 await this.m_semaphore.WaitAsync(); | ||||
|                 await this.m_semaphoreForSend.WaitAsync(); | ||||
|  | ||||
|                 while (length > 0) | ||||
|                 { | ||||
|                     var r = await this.Socket.SendAsync(new ArraySegment<byte>(buffer, offset, length), SocketFlags.None, CancellationToken.None); | ||||
|                     var r = await this.m_socket.SendAsync(new ArraySegment<byte>(buffer, offset, length), SocketFlags.None, CancellationToken.None); | ||||
|                     if (r == 0 && length > 0) | ||||
|                     { | ||||
|                         throw new Exception("发送数据不完全"); | ||||
| @@ -398,7 +385,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 this.m_semaphore.Release(); | ||||
|                 this.m_semaphoreForSend.Release(); | ||||
|             } | ||||
|         } | ||||
| #else | ||||
| @@ -410,11 +397,11 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 await this.m_semaphore.WaitAsync(); | ||||
|                 await this.m_semaphoreForSend.WaitAsync(); | ||||
|  | ||||
|                 while (length > 0) | ||||
|                 { | ||||
|                     var r = this.Socket.Send(buffer, offset, length, SocketFlags.None); | ||||
|                     var r = this.m_socket.Send(buffer, offset, length, SocketFlags.None); | ||||
|                     if (r == 0 && length > 0) | ||||
|                     { | ||||
|                         throw new Exception("发送数据不完全"); | ||||
| @@ -425,7 +412,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 this.m_semaphore.Release(); | ||||
|                 this.m_semaphoreForSend.Release(); | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
| @@ -443,23 +430,6 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|         this.OnBreakOut?.Invoke(this, manual, msg); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 释放对象 | ||||
|     /// </summary> | ||||
|     /// <param name="disposing"></param> | ||||
|     protected virtual void Dispose(bool disposing) | ||||
|     { | ||||
|         if (!this.m_disposedValue) | ||||
|         { | ||||
|             if (disposing) | ||||
|             { | ||||
|             } | ||||
|  | ||||
|             this.m_disposedValue = true; | ||||
|         } | ||||
|         base.Dispose(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 当发生异常的时候 | ||||
|     /// </summary> | ||||
| @@ -481,7 +451,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 this.PrivateBreakOut(false, ex.Message); | ||||
|                 this.PrivateBreakOut(false, ex.ToString()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -514,12 +484,20 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|  | ||||
|     private void OnReceivePeriod(long value) | ||||
|     { | ||||
|         this.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value); | ||||
|         this.m_receiveBufferSize = Math.Max(TouchSocketUtility.HitBufferLength(value), this.MinBufferSize); | ||||
|         if (this.m_socket != null) | ||||
|         { | ||||
|             this.m_socket.ReceiveBufferSize = this.m_receiveBufferSize; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void OnSendPeriod(long value) | ||||
|     { | ||||
|         this.SendBufferSize = TouchSocketUtility.HitBufferLength(value); | ||||
|         this.m_sendBufferSize = Math.Max(TouchSocketUtility.HitBufferLength(value), this.MinBufferSize); | ||||
|         if (this.m_socket != null) | ||||
|         { | ||||
|             this.m_socket.SendBufferSize = this.m_sendBufferSize; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void PrivateBreakOut(bool manual, string msg) | ||||
| @@ -548,11 +526,11 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|             this.HandleBuffer(byteBlock); | ||||
|             try | ||||
|             { | ||||
|                 var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength)); | ||||
|                 var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, this.MaxBufferSize)); | ||||
|                 e.UserToken = newByteBlock; | ||||
|                 e.SetBuffer(newByteBlock.Buffer, 0, newByteBlock.Capacity); | ||||
|  | ||||
|                 if (!this.Socket.ReceiveAsync(e)) | ||||
|                 if (!this.m_socket.ReceiveAsync(e)) | ||||
|                 { | ||||
|                     this.m_bufferRate += 2; | ||||
|                     this.ProcessReceived(e); | ||||
| @@ -560,7 +538,7 @@ public class TcpCore : SocketAsyncEventArgs, IDisposable, ISender | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 this.PrivateBreakOut(false, ex.Message); | ||||
|                 this.PrivateBreakOut(false, ex.ToString()); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|   | ||||
| @@ -39,23 +39,10 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|         public SocketClient() | ||||
|         { | ||||
|             this.Protocol = Protocol.Tcp; | ||||
|             //this.m_receiveCounter = new ValueCounter | ||||
|             //{ | ||||
|             //    Period = TimeSpan.FromSeconds(1), | ||||
|             //    OnPeriod = this.OnReceivePeriod | ||||
|             //}; | ||||
|             //m_sendCounter = new ValueCounter | ||||
|             //{ | ||||
|             //    Period = TimeSpan.FromSeconds(1), | ||||
|             //    OnPeriod = this.OnSendPeriod | ||||
|             //}; | ||||
|         } | ||||
|  | ||||
|         #region 变量 | ||||
|  | ||||
|         //private ValueCounter m_receiveCounter; | ||||
|         //private ValueCounter m_sendCounter; | ||||
|         //private long m_bufferRate = 1; | ||||
|         private DelaySender m_delaySender; | ||||
|  | ||||
|         private TcpCore m_tcpCore; | ||||
| @@ -127,36 +114,23 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|         #endregion 属性 | ||||
|  | ||||
|         #region Internal | ||||
|  | ||||
|         internal Task AuthenticateAsync(ServiceSslOption sslOption) | ||||
|         { | ||||
|             return this.m_tcpCore.AuthenticateAsync(sslOption); | ||||
|         } | ||||
|         internal void BeginReceive() | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 this.m_tcpCore.BeginIocpReceive(); | ||||
|                 //if (this.ReceiveType == ReceiveType.Iocp) | ||||
|                 //{ | ||||
|                 //    //var eventArgs = new SocketAsyncEventArgs(); | ||||
|                 //    //eventArgs.Completed += this.EventArgs_Completed; | ||||
|                 //    //var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize); | ||||
|                 //    //eventArgs.UserToken = byteBlock; | ||||
|                 //    //eventArgs.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity); | ||||
|                 //    //if (!this.MainSocket.ReceiveAsync(eventArgs)) | ||||
|                 //    //{ | ||||
|                 //    //    this.ProcessReceived(eventArgs); | ||||
|                 //    //} | ||||
|  | ||||
|                 //} | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 this.BreakOut(default, false, ex.Message); | ||||
|                 this.BreakOut(false, ex.ToString()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         internal Task AuthenticateAsync(ServiceSslOption sslOption) | ||||
|         { | ||||
|             return this.m_tcpCore.AuthenticateAsync(sslOption); | ||||
|         } | ||||
|  | ||||
|         internal Task BeginReceiveSsl() | ||||
|         { | ||||
|             return this.m_tcpCore.BeginSslReceive(); | ||||
| @@ -220,17 +194,33 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|  | ||||
|             if (this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty) is DelaySenderOption senderOption) | ||||
|             { | ||||
|                 this.m_delaySender = new DelaySender(senderOption, this.MainSocket.AbsoluteSend); | ||||
|                 this.m_delaySender = new DelaySender(senderOption, this.GetTcpCore().Send); | ||||
|             } | ||||
|  | ||||
|             var tcpCore = this.Service.RentTcpCore(); | ||||
|             tcpCore.Reset(socket); | ||||
|             tcpCore.OnReceived = this.HandleReceived; | ||||
|             tcpCore.OnBreakOut = this.BreakOut; | ||||
|             tcpCore.OnBreakOut = this.TcpCoreBreakOut; | ||||
|             if (this.Config.GetValue(TouchSocketConfigExtension.MinBufferSizeProperty) is int minValue) | ||||
|             { | ||||
|                 tcpCore.MinBufferSize = minValue; | ||||
|             } | ||||
|  | ||||
|             if (this.Config.GetValue(TouchSocketConfigExtension.MaxBufferSizeProperty) is int maxValue) | ||||
|             { | ||||
|                 tcpCore.MaxBufferSize = maxValue; | ||||
|             } | ||||
|             this.m_tcpCore = tcpCore; | ||||
|         } | ||||
|  | ||||
|         private void BreakOut(TcpCore core, bool manual, string msg) | ||||
|  | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 中断连接 | ||||
|         /// </summary> | ||||
|         /// <param name="manual"></param> | ||||
|         /// <param name="msg"></param> | ||||
|         protected void BreakOut(bool manual, string msg) | ||||
|         { | ||||
|             if (this.GetSocketCliectCollection().TryRemove(this.Id, out _)) | ||||
|             { | ||||
| @@ -273,7 +263,10 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|                 this.Logger.Log(LogLevel.Error, this, "在处理数据时发生错误", ex); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void TcpCoreBreakOut(TcpCore core, bool manual, string msg) | ||||
|         { | ||||
|             this.BreakOut(manual, msg); | ||||
|         } | ||||
|         #endregion Internal | ||||
|  | ||||
|         #region 事件&委托 | ||||
| @@ -368,10 +361,6 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|             return EasyTask.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private Task PrivateOnDisconnecting(object obj) | ||||
|         { | ||||
|             return this.OnDisconnecting((DisconnectEventArgs)obj); | ||||
|         } | ||||
|  | ||||
|         private async Task PrivateOnDisconnected(object obj) | ||||
|         { | ||||
| @@ -388,30 +377,25 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|             { | ||||
|                 var tcp = this.m_tcpCore; | ||||
|                 this.m_tcpCore = null; | ||||
|                 this.Service?.ReturnTcpCore(tcp); | ||||
|                 this.Service.ReturnTcpCore(tcp); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private Task PrivateOnDisconnecting(object obj) | ||||
|         { | ||||
|             return this.OnDisconnecting((DisconnectEventArgs)obj); | ||||
|         } | ||||
|         #endregion 事件&委托 | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int ReceiveBufferSize | ||||
|         { | ||||
|             get => this.GetTcpCore().ReceiveBufferSize; | ||||
|             set | ||||
|             { | ||||
|                 this.GetTcpCore().ReceiveBufferSize = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int SendBufferSize | ||||
|         { | ||||
|             get => this.GetTcpCore().SendBufferSize; | ||||
|             set | ||||
|             { | ||||
|                 this.GetTcpCore().SendBufferSize = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
| @@ -423,7 +407,7 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|                 { | ||||
|                     Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, msg)); | ||||
|                     this.MainSocket.TryClose(); | ||||
|                     this.BreakOut(default, true, msg); | ||||
|                     this.BreakOut(true, msg); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -504,30 +488,13 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|                 if (this.Online) | ||||
|                 { | ||||
|                     Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开")); | ||||
|                     this.BreakOut(default, true, $"{nameof(Dispose)}主动断开"); | ||||
|                     this.BreakOut(true, $"{nameof(Dispose)}主动断开"); | ||||
|                 } | ||||
|  | ||||
|                 base.Dispose(disposing); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当即将发送时,如果覆盖父类方法,则不会触发插件。 | ||||
|         /// </summary> | ||||
|         /// <param name="buffer">数据缓存区</param> | ||||
|         /// <param name="offset">偏移</param> | ||||
|         /// <param name="length">长度</param> | ||||
|         /// <returns>返回值表示是否允许发送</returns> | ||||
|         protected virtual async Task<bool> SendingData(byte[] buffer, int offset, int length) | ||||
|         { | ||||
|             if (this.PluginsManager.GetPluginCount(nameof(ITcpSendingPlugin.OnTcpSending)) > 0) | ||||
|             { | ||||
|                 var args = new SendingEventArgs(buffer, offset, length); | ||||
|                 await this.PluginsManager.RaiseAsync(nameof(ITcpSendingPlugin.OnTcpSending), this, args).ConfigureAwait(false); | ||||
|                 return args.IsPermitOperation; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当Id更新的时候触发 | ||||
| @@ -570,6 +537,24 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|             return Task.FromResult(false); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 当即将发送时,如果覆盖父类方法,则不会触发插件。 | ||||
|         /// </summary> | ||||
|         /// <param name="buffer">数据缓存区</param> | ||||
|         /// <param name="offset">偏移</param> | ||||
|         /// <param name="length">长度</param> | ||||
|         /// <returns>返回值表示是否允许发送</returns> | ||||
|         protected virtual async Task<bool> SendingData(byte[] buffer, int offset, int length) | ||||
|         { | ||||
|             if (this.PluginsManager.GetPluginCount(nameof(ITcpSendingPlugin.OnTcpSending)) > 0) | ||||
|             { | ||||
|                 var args = new SendingEventArgs(buffer, offset, length); | ||||
|                 await this.PluginsManager.RaiseAsync(nameof(ITcpSendingPlugin.OnTcpSending), this, args).ConfigureAwait(false); | ||||
|                 return args.IsPermitOperation; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 设置适配器,该方法不会检验<see cref="CanSetDataHandlingAdapter"/>的值。 | ||||
|         /// </summary> | ||||
| @@ -624,6 +609,11 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|         { | ||||
|             if (this.SendingData(buffer, offset, length).GetFalseAwaitResult()) | ||||
|             { | ||||
|                 if (this.m_delaySender != null) | ||||
|                 { | ||||
|                     this.m_delaySender.Send(new QueueDataBytes(buffer, offset, length)); | ||||
|                     return; | ||||
|                 } | ||||
|                 this.GetTcpCore().Send(buffer, offset, length); | ||||
|             } | ||||
|         } | ||||
| @@ -855,18 +845,19 @@ namespace ThingsGateway.Foundation.Sockets | ||||
|  | ||||
|         private Receiver m_receiver; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IReceiver CreateReceiver() | ||||
|         { | ||||
|             return this.m_receiver ??= new Receiver(this); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public void ClearReceiver() | ||||
|         { | ||||
|             this.m_receiver = null; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IReceiver CreateReceiver() | ||||
|         { | ||||
|             return this.m_receiver ??= new Receiver(this); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user