mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-19 02:53:06 +08:00
Improve connection disposal.
This commit is contained in:
@@ -23,7 +23,7 @@ namespace MQTTnet.Implementations
|
||||
_logger = logger.CreateChildLogger(nameof(MqttTcpServerAdapter));
|
||||
}
|
||||
|
||||
public Action<MqttServerAdapterClientAcceptedEventArgs> ClientAcceptedHandler { get; set; }
|
||||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||
|
||||
public async Task StartAsync(IMqttServerOptions options)
|
||||
{
|
||||
@@ -39,7 +39,7 @@ namespace MQTTnet.Implementations
|
||||
_listener.Control.NoDelay = options.DefaultEndpointOptions.NoDelay;
|
||||
_listener.Control.KeepAlive = true;
|
||||
_listener.Control.QualityOfService = SocketQualityOfService.LowLatency;
|
||||
_listener.ConnectionReceived += AcceptDefaultEndpointConnectionsAsync;
|
||||
_listener.ConnectionReceived += OnConnectionReceivedAsync;
|
||||
|
||||
await _listener.BindServiceNameAsync(options.DefaultEndpointOptions.Port.ToString(), SocketProtectionLevel.PlainSocket);
|
||||
}
|
||||
@@ -54,30 +54,51 @@ namespace MQTTnet.Implementations
|
||||
{
|
||||
if (_listener != null)
|
||||
{
|
||||
_listener.ConnectionReceived -= AcceptDefaultEndpointConnectionsAsync;
|
||||
_listener.ConnectionReceived -= OnConnectionReceivedAsync;
|
||||
}
|
||||
|
||||
_listener?.Dispose();
|
||||
_listener = null;
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
StopAsync().GetAwaiter().GetResult();
|
||||
_listener?.Dispose();
|
||||
_listener = null;
|
||||
}
|
||||
|
||||
private void AcceptDefaultEndpointConnectionsAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
|
||||
private async void OnConnectionReceivedAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(args.Socket, _options), new MqttPacketFormatterAdapter(), _logger);
|
||||
ClientAcceptedHandler?.Invoke(new MqttServerAdapterClientAcceptedEventArgs(clientAdapter));
|
||||
var clientHandler = ClientHandler;
|
||||
if (clientHandler != null)
|
||||
{
|
||||
using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(args.Socket, _options), new MqttPacketFormatterAdapter(), _logger))
|
||||
{
|
||||
await clientHandler(clientAdapter).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while accepting connection at default endpoint.");
|
||||
if (exception is ObjectDisposedException)
|
||||
{
|
||||
// It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed.
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Error(exception, "Error while handling client connection.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
args.Socket.Dispose();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while cleaning up client connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace MQTTnet.Implementations
|
||||
_logger = logger.CreateChildLogger(nameof(MqttTcpServerAdapter));
|
||||
}
|
||||
|
||||
public Action<MqttServerAdapterClientAcceptedEventArgs> ClientAcceptedHandler { get; set; }
|
||||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||
|
||||
public Task StartAsync(IMqttServerOptions options)
|
||||
{
|
||||
@@ -89,7 +89,7 @@ namespace MQTTnet.Implementations
|
||||
_cancellationTokenSource.Token,
|
||||
_logger)
|
||||
{
|
||||
ClientAcceptedHandler = OnClientAccepted
|
||||
ClientHandler = OnClientAcceptedAsync
|
||||
};
|
||||
|
||||
listenerV4.Start();
|
||||
@@ -105,7 +105,7 @@ namespace MQTTnet.Implementations
|
||||
_cancellationTokenSource.Token,
|
||||
_logger)
|
||||
{
|
||||
ClientAcceptedHandler = OnClientAccepted
|
||||
ClientHandler = OnClientAcceptedAsync
|
||||
};
|
||||
|
||||
listenerV6.Start();
|
||||
@@ -113,9 +113,15 @@ namespace MQTTnet.Implementations
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClientAccepted(MqttServerAdapterClientAcceptedEventArgs eventArgs)
|
||||
private Task OnClientAcceptedAsync(IMqttChannelAdapter channelAdapter)
|
||||
{
|
||||
ClientAcceptedHandler?.Invoke(eventArgs);
|
||||
var clientHandler = ClientHandler;
|
||||
if (clientHandler == null)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
return clientHandler(channelAdapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace MQTTnet.Implementations
|
||||
}
|
||||
}
|
||||
|
||||
public Action<MqttServerAdapterClientAcceptedEventArgs> ClientAcceptedHandler { get; set; }
|
||||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||
|
||||
public void Start()
|
||||
{
|
||||
@@ -97,11 +97,14 @@ namespace MQTTnet.Implementations
|
||||
private async Task TryHandleClientConnectionAsync(Socket clientSocket)
|
||||
{
|
||||
Stream stream = null;
|
||||
EndPoint remoteEndPoint = null;
|
||||
|
||||
try
|
||||
{
|
||||
remoteEndPoint = clientSocket.RemoteEndPoint;
|
||||
|
||||
_logger.Verbose("Client '{0}' accepted by TCP listener '{1}, {2}'.",
|
||||
clientSocket.RemoteEndPoint,
|
||||
remoteEndPoint,
|
||||
_socket.LocalEndPoint,
|
||||
_addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6");
|
||||
|
||||
@@ -116,8 +119,14 @@ namespace MQTTnet.Implementations
|
||||
stream = sslStream;
|
||||
}
|
||||
|
||||
var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(stream), new MqttPacketFormatterAdapter(), _logger);
|
||||
ClientAcceptedHandler?.Invoke(new MqttServerAdapterClientAcceptedEventArgs(clientAdapter));
|
||||
var clientHandler = ClientHandler;
|
||||
if (clientHandler != null)
|
||||
{
|
||||
using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(stream), new MqttPacketFormatterAdapter(), _logger))
|
||||
{
|
||||
await clientHandler(clientAdapter).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -127,20 +136,29 @@ namespace MQTTnet.Implementations
|
||||
return;
|
||||
}
|
||||
|
||||
if (exception is SocketException socketException && socketException.SocketErrorCode == SocketError.OperationAborted)
|
||||
if (exception is SocketException socketException &&
|
||||
socketException.SocketErrorCode == SocketError.OperationAborted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Error(exception, "Error while handling client connection.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
// Dispose already allocated resources.
|
||||
stream?.Dispose();
|
||||
clientSocket?.Dispose();
|
||||
|
||||
_logger.Verbose("Client '{0}' disconnected at TCP listener '{1}, {2}'.",
|
||||
remoteEndPoint,
|
||||
_socket.LocalEndPoint,
|
||||
_addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6");
|
||||
}
|
||||
catch (Exception disposeException)
|
||||
{
|
||||
_logger.Error(disposeException, "Error while cleanup of broken connection.");
|
||||
_logger.Error(disposeException, "Error while cleaning up client connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.WebSockets;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
Reference in New Issue
Block a user