diff --git a/Frameworks/MQTTnet.AspnetCore/MQTTnet.AspnetCore.csproj b/Frameworks/MQTTnet.AspnetCore/MQTTnet.AspnetCore.csproj index 5556b11c..fbde3f2b 100644 --- a/Frameworks/MQTTnet.AspnetCore/MQTTnet.AspnetCore.csproj +++ b/Frameworks/MQTTnet.AspnetCore/MQTTnet.AspnetCore.csproj @@ -6,6 +6,10 @@ 2.5.2.0 + + RELEASE;NETSTANDARD2_0 + + diff --git a/Frameworks/MQTTnet.NetStandard/Adapter/MqttChannelAdapter.cs b/Frameworks/MQTTnet.NetStandard/Adapter/MqttChannelAdapter.cs index bf89fabf..2a9815d4 100644 --- a/Frameworks/MQTTnet.NetStandard/Adapter/MqttChannelAdapter.cs +++ b/Frameworks/MQTTnet.NetStandard/Adapter/MqttChannelAdapter.cs @@ -31,23 +31,23 @@ namespace MQTTnet.Adapter public IMqttPacketSerializer PacketSerializer { get; } - public async Task ConnectAsync(TimeSpan timeout) + public Task ConnectAsync(TimeSpan timeout) { _logger.Info("Connecting [Timeout={0}]", timeout); - await ExecuteAndWrapExceptionAsync(() => _channel.ConnectAsync().TimeoutAfter(timeout)); + return ExecuteAndWrapExceptionAsync(() => _channel.ConnectAsync().TimeoutAfter(timeout)); } - public async Task DisconnectAsync(TimeSpan timeout) + public Task DisconnectAsync(TimeSpan timeout) { _logger.Info("Disconnecting [Timeout={0}]", timeout); - await ExecuteAndWrapExceptionAsync(() => _channel.DisconnectAsync().TimeoutAfter(timeout)); + return ExecuteAndWrapExceptionAsync(() => _channel.DisconnectAsync().TimeoutAfter(timeout)); } - public async Task SendPacketsAsync(TimeSpan timeout, CancellationToken cancellationToken, IEnumerable packets) + public Task SendPacketsAsync(TimeSpan timeout, CancellationToken cancellationToken, IEnumerable packets) { - await ExecuteAndWrapExceptionAsync(async () => + return ExecuteAndWrapExceptionAsync(async () => { await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try diff --git a/Frameworks/MQTTnet.NetStandard/Internal/TaskExtensions.cs b/Frameworks/MQTTnet.NetStandard/Internal/TaskExtensions.cs index 6acb71ef..bfa01bdb 100644 --- a/Frameworks/MQTTnet.NetStandard/Internal/TaskExtensions.cs +++ b/Frameworks/MQTTnet.NetStandard/Internal/TaskExtensions.cs @@ -9,13 +9,15 @@ namespace MQTTnet.Internal { public static async Task TimeoutAfter(this Task task, TimeSpan timeout) { - using (var cancellationTokenSource = new CancellationTokenSource()) + if (task == null) throw new ArgumentNullException(nameof(task)); + + using (var timeoutCts = new CancellationTokenSource()) { try { - var timeoutTask = Task.Delay(timeout, cancellationTokenSource.Token); + var timeoutTask = Task.Delay(timeout, timeoutCts.Token); var finishedTask = await Task.WhenAny(timeoutTask, task).ConfigureAwait(false); - + if (finishedTask == timeoutTask) { throw new MqttCommunicationTimedOutException(); @@ -33,18 +35,20 @@ namespace MQTTnet.Internal } finally { - cancellationTokenSource.Cancel(); + timeoutCts.Cancel(); } } } public static async Task TimeoutAfter(this Task task, TimeSpan timeout) { - using (var cancellationTokenSource = new CancellationTokenSource()) + if (task == null) throw new ArgumentNullException(nameof(task)); + + using (var timeoutCts = new CancellationTokenSource()) { try { - var timeoutTask = Task.Delay(timeout, cancellationTokenSource.Token); + var timeoutTask = Task.Delay(timeout, timeoutCts.Token); var finishedTask = await Task.WhenAny(timeoutTask, task).ConfigureAwait(false); if (finishedTask == timeoutTask) @@ -66,7 +70,7 @@ namespace MQTTnet.Internal } finally { - cancellationTokenSource.Cancel(); + timeoutCts.Cancel(); } } } diff --git a/Frameworks/MQTTnet.NetStandard/MQTTnet.Netstandard.csproj b/Frameworks/MQTTnet.NetStandard/MQTTnet.Netstandard.csproj index f4018cb5..abcc8658 100644 --- a/Frameworks/MQTTnet.NetStandard/MQTTnet.Netstandard.csproj +++ b/Frameworks/MQTTnet.NetStandard/MQTTnet.Netstandard.csproj @@ -36,6 +36,10 @@ + + RELEASE;NETSTANDARD1_3 + + diff --git a/Frameworks/MQTTnet.NetStandard/Server/MqttClientSession.cs b/Frameworks/MQTTnet.NetStandard/Server/MqttClientSession.cs index 275fcb1b..c5f16a9e 100644 --- a/Frameworks/MQTTnet.NetStandard/Server/MqttClientSession.cs +++ b/Frameworks/MQTTnet.NetStandard/Server/MqttClientSession.cs @@ -143,16 +143,16 @@ namespace MQTTnet.Server private Task ProcessReceivedPacketAsync(IMqttChannelAdapter adapter, MqttBasePacket packet, CancellationToken cancellationToken) { - if (packet is MqttPingReqPacket) - { - return adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, new MqttPingRespPacket()); - } - if (packet is MqttPublishPacket publishPacket) { return HandleIncomingPublishPacketAsync(adapter, publishPacket, cancellationToken); } + if (packet is MqttPingReqPacket) + { + return adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, new MqttPingRespPacket()); + } + if (packet is MqttPubRelPacket pubRelPacket) { return HandleIncomingPubRelPacketAsync(adapter, pubRelPacket, cancellationToken); diff --git a/Frameworks/MQTTnet.NetStandard/Server/MqttClientSessionsManager.cs b/Frameworks/MQTTnet.NetStandard/Server/MqttClientSessionsManager.cs index 870e5e09..f65ed2ba 100644 --- a/Frameworks/MQTTnet.NetStandard/Server/MqttClientSessionsManager.cs +++ b/Frameworks/MQTTnet.NetStandard/Server/MqttClientSessionsManager.cs @@ -168,7 +168,7 @@ namespace MQTTnet.Server lock (_sessions) { - foreach (var clientSession in _sessions.Values.ToList()) + foreach (var clientSession in _sessions.Values) { clientSession.EnqueueApplicationMessage(applicationMessage); } diff --git a/README.md b/README.md index 57dfce2e..5d3e1867 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov * TLS 1.2 support for client and server (but not UWP servers) * Extensible communication channels (i.e. In-Memory, TCP, TCP+TLS, WS) * Lightweight (only the low level implementation of MQTT, no overhead) -* Performance optimized (processing ~27.000 messages / second)* +* Performance optimized (processing ~30.000 messages / second)* * Interfaces included for mocking and testing * Access to internal trace messages * Unit tested (70+ tests) diff --git a/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs b/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs index 301e0fec..1c72b06a 100644 --- a/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs +++ b/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs @@ -43,33 +43,6 @@ namespace MQTTnet.TestApp.NetCore var client = new MqttFactory().CreateMqttClient(); - client.Connected += async (s, e) => - { - Console.WriteLine("### CONNECTED WITH SERVER ###"); - - await client.SubscribeAsync(new List - { - new TopicFilter("#") - }); - - Console.WriteLine("### SUBSCRIBED ###"); - }; - - client.Disconnected += async (s, e) => - { - Console.WriteLine("### DISCONNECTED FROM SERVER ###"); - await Task.Delay(TimeSpan.FromSeconds(5)); - - try - { - await client.ConnectAsync(options); - } - catch - { - Console.WriteLine("### RECONNECTING FAILED ###"); - } - }; - try { await client.ConnectAsync(options); @@ -79,24 +52,12 @@ namespace MQTTnet.TestApp.NetCore Console.WriteLine("### CONNECTING FAILED ###" + Environment.NewLine + exception); } - Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###"); - - var testMessageCount = 10000; var message = CreateMessage(); - var stopwatch = Stopwatch.StartNew(); - for (var i = 0; i < testMessageCount; i++) - { - await client.PublishAsync(message); - } - - stopwatch.Stop(); - Console.WriteLine($"Sent 10.000 messages within {stopwatch.ElapsedMilliseconds} ms ({stopwatch.ElapsedMilliseconds / (float)testMessageCount} ms / message)."); - var messages = new[] { message }; + + var stopwatch = Stopwatch.StartNew(); + var sentMessagesCount = 0; - - stopwatch.Restart(); - while (stopwatch.ElapsedMilliseconds < 1000) { await client.PublishAsync(messages).ConfigureAwait(false); @@ -104,6 +65,17 @@ namespace MQTTnet.TestApp.NetCore } Console.WriteLine($"Sending {sentMessagesCount} messages per second."); + + stopwatch.Restart(); + + var testMessageCount = 10000; + for (var i = 0; i < testMessageCount; i++) + { + await client.PublishAsync(message); + } + + stopwatch.Stop(); + Console.WriteLine($"Sent 10.000 messages within {stopwatch.ElapsedMilliseconds} ms ({stopwatch.ElapsedMilliseconds / (float)testMessageCount} ms / message)."); var last = DateTime.Now; var msgCount = 0;