Skip to content

Socket.Connect methods that connect to multiple endpoints are broken on Unix #16263

Description

@ericeil

Unlike Windows, the sockets API on Linux and OSX does not allow a single socket to attempt more than one connection. We had attempted to do this on Linux, but it did not work (see #16238).

Socket has multiple methods that depend on being able to try connections to multiple endpoints on a single socket:

public void Connect(IPAddress[] addresses, int port)

...attempts to connect to each of addresses, returning when one of them is successful.

public void Connect(string host, int port)

...does a DNS lookup, which may return multiple addresses, then attempts to connect to each of them until successful.

public void Connect(EndPoint remoteEP)

If this is passed a DnsEndPoint, then this behaves the same as Connect(string, int), trying all resolved addresses.

Additionally, we support async variants of all of these.

On Unix we currently "fake" this by creating multiple temporary sockets behind the scenes, trying to connect each of them to a different address. If one succeeds, we immediately disconnect it and connect the "real" socket to that address. This workaround has some possibly unacceptable implications:

  1. Whichever endpoint we finally choose, we will end up connecting to it twice, once for the "probe" connection, to see if it will work, and again for the "real" connection. This will cause issues for servers that do not expect more than one connection, for load balancers that try to distribute connections, etc. It's also a lot of undesired network overhead.

  2. Even though the first connection attempt succeeded, the second will not necessarily succeed. This is especially true in scenarios like DNS-based load balancing. So we have a functional issue here, where we may fail to connect the "real" socket in cases where we would have succeeded.

I do not think we should leave this as-is, as it will create too many unexpected strange behaviors in code that uses these, expecting them to behave the same way as they do on Windows. So I propose doing one of the following:

a) Remove the Connect overloads that take multiple endpoints, and the DnsEndpoint type, from the public contracts.

-- or --

b) Change these Connect overloads to throw PlatformNotSupportedException on Unix, Also, change Connect(EndPoint, int) to throw PlatformNotSupportedException if passed a DnsEndPoint.

In either case, we should provide sample code for how to code equivalent behavior using the remaining APIs.

@stephentoub, @pgavlin, @CIPop, @davidsh, @SidharthNabar, please provide feedback.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions