-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
TcpClient has public constructor that takes host name and port and when used, it connects underlying Socket. However the behavior is different when creating TcpClient and calling Connect method to the same host.
using System.Net.Sockets;
string host = "localhost";
var client1 = new TcpClient();
client1.Connect(host, 8080);
Console.WriteLine(client1.Client.LocalEndPoint);
var client2 = new TcpClient();
client2.ConnectAsync(host, 8080).GetAwaiter().GetResult();
Console.WriteLine(client2.Client.LocalEndPoint);
var client3 = new TcpClient(host, 8080);
Console.WriteLine(client3.Client.LocalEndPoint);will produce something like
[::ffff:127.0.0.1]:51920
[::ffff:127.0.0.1]:51922
127.0.0.1:51924
So in some cases use dual mode socket and sometimes we use socket for specific address family. Connect and ConnectAsync produce same result in example above (localhost resolves to single IPv4 address) but ConnectAsync use Socket.ConnectAsync while the synchronous implementation use implementation from TcpClient and that can produce different results.
Also documentation (https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient.-ctor?view=net-6.0#system-net-sockets-tcpclient-ctor(system-string-system-int32)) claims that IPv6 will be preferred when available but that is not what the code really does:
runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs
Lines 144 to 150 in a074a2d
| IPAddress[] addresses = Dns.GetHostAddresses(hostname); | |
| ExceptionDispatchInfo? lastex = null; | |
| try | |
| { | |
| foreach (IPAddress address in addresses) | |
| { |
While somebody may depend on this particular behavior, it seems like it would make sense to decease number of Connect implementations and overall behavior variations.
related to #63162