diff --git a/src/System.Net.Sockets/src/Resources/Strings.resx b/src/System.Net.Sockets/src/Resources/Strings.resx index 328f67c37120..37c5e994715a 100644 --- a/src/System.Net.Sockets/src/Resources/Strings.resx +++ b/src/System.Net.Sockets/src/Resources/Strings.resx @@ -273,4 +273,7 @@ Argument must be between {0} and {1}. + + Sockets on this platform are invalid for use after a failed connection attempt, and as a result do not support attempts to connect to multiple endpoints. Use the static Connect methods or the instance Connect methods that take a single, non-DNS endpoint. + \ No newline at end of file diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index 4744c05e36cf..a5e0ff0aac6c 100644 --- a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -980,77 +980,18 @@ public void Connect(IPAddress[] addresses, int port) { throw new NotSupportedException(SR.net_invalidversion); } + ThrowIfNotSupportsMultipleConnectAttempts(); - // Disable CS0162: Unreachable code detected - // - // SuportsMultipleConnectAttempts is a constant; when false, the following lines will trigger CS0162. -#pragma warning disable 162 Exception lastex = null; - if (SocketPal.SupportsMultipleConnectAttempts) + foreach (IPAddress address in addresses) { - foreach (IPAddress address in addresses) - { - if (CanTryAddressFamily(address.AddressFamily)) - { - try - { - Connect(new IPEndPoint(address, port)); - lastex = null; - break; - } - catch (Exception ex) - { - if (ExceptionCheck.IsFatal(ex)) - { - throw; - } - lastex = ex; - } - } - } - } - else - { - EndPoint endpoint = null; - foreach (IPAddress address in addresses) - { - if (CanTryAddressFamily(address.AddressFamily)) - { - Socket attemptSocket = null; - try - { - attemptSocket = new Socket(_addressFamily, _socketType, _protocolType); - if (IsDualMode) - { - attemptSocket.DualMode = true; - } - - var attemptEndpoint = new IPEndPoint(address, port); - attemptSocket.Connect(attemptEndpoint); - endpoint = attemptEndpoint; - lastex = null; - break; - } - catch (Exception ex) - { - lastex = ex; - } - finally - { - if (attemptSocket != null) - { - attemptSocket.Dispose(); - } - } - } - } - - if (endpoint != null) + if (CanTryAddressFamily(address.AddressFamily)) { try { - Connect(endpoint); + Connect(new IPEndPoint(address, port)); lastex = null; + break; } catch (Exception ex) { @@ -1062,7 +1003,6 @@ public void Connect(IPAddress[] addresses, int port) } } } -#pragma warning restore if (lastex != null) { @@ -2415,6 +2355,8 @@ internal IAsyncResult BeginConnect(string host, int port, AsyncCallback requestC throw new InvalidOperationException(SR.net_sockets_mustnotlisten); } + ThrowIfNotSupportsMultipleConnectAttempts(); + // Here, want to flow the context. No need to lock. MultipleAddressConnectAsyncResult result = new MultipleAddressConnectAsyncResult(null, port, this, state, requestCallback); result.StartPostingAsyncOp(false); @@ -2438,6 +2380,14 @@ internal IAsyncResult BeginConnect(string host, int port, AsyncCallback requestC return result; } + private static void ThrowIfNotSupportsMultipleConnectAttempts() + { + if (!SocketPal.SupportsMultipleConnectAttempts) + { + throw new PlatformNotSupportedException(SR.net_sockets_connect_multiaddress_notsupported); + } + } + internal IAsyncResult BeginConnect(IPAddress address, int port, AsyncCallback requestCallback, object state) { if (s_loggingEnabled) @@ -2502,6 +2452,7 @@ internal IAsyncResult BeginConnect(IPAddress[] addresses, int port, AsyncCallbac { throw new InvalidOperationException(SR.net_sockets_mustnotlisten); } + ThrowIfNotSupportsMultipleConnectAttempts(); // Set up the result to capture the context. No need for a lock. MultipleAddressConnectAsyncResult result = new MultipleAddressConnectAsyncResult(addresses, port, this, state, requestCallback); @@ -4408,6 +4359,8 @@ public bool ConnectAsync(SocketAsyncEventArgs e) throw new NotSupportedException(SR.net_invalidversion); } + ThrowIfNotSupportsMultipleConnectAttempts(); + MultipleConnectAsync multipleConnectAsync = new SingleSocketMultipleConnectAsync(this, true); e.StartOperationCommon(this); @@ -4518,6 +4471,10 @@ public static bool ConnectAsync(SocketType socketType, ProtocolType protocolType // Disable CS0162 and CS0429: Unreachable code detected // // SuportsMultipleConnectAttempts is a constant; when false, the following lines will trigger CS0162 or CS0429. + // + // This is the only *Connect* API that actually supports multiple endpoint attempts, as it's responsible + // for creating each Socket instance and can create one per attempt (with the instance methods, once a + // connect fails, on unix systems that socket can't be used for subsequent connect attempts). #pragma warning disable 162, 429 multipleConnectAsync = SocketPal.SupportsMultipleConnectAttempts ? (MultipleConnectAsync)(new DualSocketMultipleConnectAsync(socketType, protocolType)) :