mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-15 00:15:15 +08:00
[Client] Fix endpoint handling (#1999)
* Fix endpoint handling * Fix different behavior for Mono framework. * Restore old properties to avoid breaking changes
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* [Client] Fix _None of the discovered or specified addresses match the socket address family._ (#1997).
|
||||
* [Client] Remove the obsolete attribute from the _WithConnectionUri_ methods (#1979).
|
||||
|
||||
* All nuget packages are now signed.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -17,7 +18,7 @@ namespace MQTTnet.Tests.Internal
|
||||
[TestMethod]
|
||||
public async Task Connect_Send_Receive()
|
||||
{
|
||||
var crossPlatformSocket = new CrossPlatformSocket();
|
||||
var crossPlatformSocket = new CrossPlatformSocket(ProtocolType.Tcp);
|
||||
await crossPlatformSocket.ConnectAsync("www.google.de", 80, CancellationToken.None);
|
||||
|
||||
var requestBuffer = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\nHost: www.google.de\r\n\r\n");
|
||||
@@ -36,7 +37,7 @@ namespace MQTTnet.Tests.Internal
|
||||
[ExpectedException(typeof(OperationCanceledException))]
|
||||
public async Task Try_Connect_Invalid_Host()
|
||||
{
|
||||
var crossPlatformSocket = new CrossPlatformSocket();
|
||||
var crossPlatformSocket = new CrossPlatformSocket(ProtocolType.Tcp);
|
||||
|
||||
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
cancellationToken.Token.Register(() => crossPlatformSocket.Dispose());
|
||||
@@ -65,7 +66,7 @@ namespace MQTTnet.Tests.Internal
|
||||
[TestMethod]
|
||||
public void Set_Options()
|
||||
{
|
||||
var crossPlatformSocket = new CrossPlatformSocket();
|
||||
var crossPlatformSocket = new CrossPlatformSocket(ProtocolType.Tcp);
|
||||
|
||||
Assert.IsFalse(crossPlatformSocket.ReuseAddress);
|
||||
crossPlatformSocket.ReuseAddress = true;
|
||||
|
||||
@@ -79,11 +79,26 @@ namespace MQTTnet.Client
|
||||
{
|
||||
if (_port.HasValue)
|
||||
{
|
||||
_remoteEndPoint = new DnsEndPoint(dns.Host, _port.Value);
|
||||
_remoteEndPoint = new DnsEndPoint(dns.Host, _port.Value, dns.AddressFamily);
|
||||
}
|
||||
else
|
||||
{
|
||||
_remoteEndPoint = new DnsEndPoint(dns.Host, tlsOptions?.UseTls == false ? MqttPorts.Default : MqttPorts.Secure);
|
||||
_remoteEndPoint = new DnsEndPoint(dns.Host, tlsOptions?.UseTls == false ? MqttPorts.Default : MqttPorts.Secure, dns.AddressFamily);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_remoteEndPoint is IPEndPoint ip)
|
||||
{
|
||||
if (ip.Port == 0)
|
||||
{
|
||||
if (_port.HasValue)
|
||||
{
|
||||
_remoteEndPoint = new IPEndPoint(ip.Address, _port.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_remoteEndPoint = new IPEndPoint(ip.Address, tlsOptions?.UseTls == false ? MqttPorts.Default : MqttPorts.Secure);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,13 +367,18 @@ namespace MQTTnet.Client
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithTcpServer(string server, int? port = null)
|
||||
public MqttClientOptionsBuilder WithTcpServer(string host, int? port = null, AddressFamily addressFamily = AddressFamily.Unspecified)
|
||||
{
|
||||
if (host == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(host));
|
||||
}
|
||||
|
||||
_tcpOptions = new MqttClientTcpOptions();
|
||||
|
||||
// The value 0 will be updated when building the options.
|
||||
// This a backward compatibility feature.
|
||||
_remoteEndPoint = new DnsEndPoint(server, port ?? 0);
|
||||
_remoteEndPoint = new DnsEndPoint(host, port ?? 0, addressFamily);
|
||||
_port = port;
|
||||
|
||||
return this;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
@@ -20,6 +21,12 @@ namespace MQTTnet.Client
|
||||
/// </summary>
|
||||
public bool? DualMode { get; set; }
|
||||
|
||||
[Obsolete("Use RemoteEndpoint or MqttClientOptionsBuilder instead.")]
|
||||
public int? Port { get; set; }
|
||||
|
||||
[Obsolete("Use RemoteEndpoint or MqttClientOptionsBuilder instead.")]
|
||||
public string Server { get; set; }
|
||||
|
||||
public LingerOption LingerState { get; set; } = new LingerOption(true, 0);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -31,11 +31,11 @@ namespace MQTTnet.Implementations
|
||||
#endif
|
||||
}
|
||||
|
||||
public CrossPlatformSocket()
|
||||
public CrossPlatformSocket(ProtocolType protocolType)
|
||||
{
|
||||
// Having this constructor is important because avoiding the address family as parameter
|
||||
// will make use of dual mode in the .net framework.
|
||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
||||
_socket = new Socket(SocketType.Stream, protocolType);
|
||||
|
||||
#if !NET5_0_OR_GREATER
|
||||
_socketDisposeAction = _socket.Dispose;
|
||||
@@ -202,9 +202,28 @@ namespace MQTTnet.Implementations
|
||||
using (cancellationToken.Register(_socketDisposeAction))
|
||||
{
|
||||
#if NET452 || NET461
|
||||
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, endPoint, null).ConfigureAwait(false);
|
||||
// This is a fix for Mono which behaves differently than dotnet.
|
||||
// The connection will not be established when the DNS endpoint is used.
|
||||
if (endPoint is DnsEndPoint dns && dns.AddressFamily == AddressFamily.Unspecified)
|
||||
{
|
||||
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, dns.Host, dns.Port, null).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, endPoint, null).ConfigureAwait(false);
|
||||
}
|
||||
#else
|
||||
await _socket.ConnectAsync(endPoint).ConfigureAwait(false);
|
||||
|
||||
// This is a fix for Mono which behaves differently than dotnet.
|
||||
// The connection will not be established when the DNS endpoint is used.
|
||||
if (endPoint is DnsEndPoint dns && dns.AddressFamily == AddressFamily.Unspecified)
|
||||
{
|
||||
await _socket.ConnectAsync(dns.Host, dns.Port).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _socket.ConnectAsync(endPoint).ConfigureAwait(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,7 @@ using MQTTnet.Channel;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Implementations
|
||||
{
|
||||
@@ -63,7 +64,7 @@ namespace MQTTnet.Implementations
|
||||
{
|
||||
if (_tcpOptions.AddressFamily == AddressFamily.Unspecified)
|
||||
{
|
||||
socket = new CrossPlatformSocket();
|
||||
socket = new CrossPlatformSocket(_tcpOptions.ProtocolType);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -98,6 +99,29 @@ namespace MQTTnet.Implementations
|
||||
socket.DualMode = _tcpOptions.DualMode.Value;
|
||||
}
|
||||
|
||||
// This block is only for backward compatibility.
|
||||
if (_tcpOptions.RemoteEndpoint == null && !string.IsNullOrEmpty(_tcpOptions.Server))
|
||||
{
|
||||
int port;
|
||||
if (_tcpOptions.Port.HasValue)
|
||||
{
|
||||
port = _tcpOptions.Port.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_tcpOptions.TlsOptions?.UseTls == true)
|
||||
{
|
||||
port = MqttPorts.Secure;
|
||||
}
|
||||
else
|
||||
{
|
||||
port = MqttPorts.Default;
|
||||
}
|
||||
}
|
||||
|
||||
_tcpOptions.RemoteEndpoint = new DnsEndPoint(_tcpOptions.Server, port, AddressFamily.Unspecified);
|
||||
}
|
||||
|
||||
await socket.ConnectAsync(_tcpOptions.RemoteEndpoint, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
Reference in New Issue
Block a user