I have a TcpClient
with Client.LocalEndPoint
and Client.RemoteEndPoint
. The connection is active (to a local TCP server).
I gather the list of TCP connections via:
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] connections = properties.GetActiveTcpConnections();
When I try to find the connection within connections
, I'm having a difficult time matching because the value/contents of Client.LocalEndPoint
and Client.RemoteEndPoint
are of a different form than those in TcpConnectionInformation
.
e.g.
Console.WriteLine(client.Client.LocalEndPoint.ToString());
// [::ffff:127.0.0.1]:55853
and
foreach (var conn in connections)
{
Console.WriteLine(conn.LocalEndPoint.ToString() + " to " + conn.RemoteEndPoint.ToString() + ": " + conn.State.ToString());
// 127.0.0.1:55853 to 127.0.0.1:8000: Established
}
As a result, this returns null:
var state = connections.FirstOrDefault(x =>
x.LocalEndPoint.Equals(client.Client.LocalEndPoint)
&& x.RemoteEndPoint.Equals(client.Client.RemoteEndPoint));
It appears that the TcpClient
is reporting a hybrid IPv6+IPv4 address, whereas TcpConnectionInformation
is reporting only the IPv4 address.
Is there an effective cross-platform way of comparing to identify the connection information?
The problem is that since Windows is now fully dual-stacked, all IP addresses are represented as Ipv4-Mapped-To-IPv6 addresses (RFC4291). These are not IPv6 addresses and cannot be routed as IPv6, they are simply used to represent IPv4 addresses on an IPv6 machine.
Quite why TcpConnectionInformation
does not also show addresses this way is unclear.
To convert them, there is a function to convert back to standard IPv4:
var local = (client.Client.LocalEndPoint as IPEndpoint)?.Address;
if (local?.IsIPv4MappedToIPv6 ?? false)
local = local.MapToIPv4();
var remote = (client.Client.RemoteEndPoint as IPEndPoint)?.Address;
if (remote?.IsIPv4MappedToIPv6 ?? false)
remote = remote.MapToIPv4();
You can also convert the other way if you want.