如何跨平台匹配TcpClient与TcpConnectionInformation的TCP连接?
跨平台匹配TcpClient与系统TCP连接的方法
问题核心在于TcpClient返回的是IPv6映射的IPv4地址(如[::ffff:127.0.0.1]:55853),而IPGlobalProperties获取的是纯IPv4地址,直接用Equals会因为地址格式不匹配失败。解决思路是统一两种地址的格式,提取实际的IP地址和端口后再对比。
方案1:使用标准化端点结构体(推荐,复用性高)
定义一个结构体处理地址格式转换,实现相等性判断:
public readonly struct StandardizedEndPoint : IEquatable<StandardizedEndPoint> { public IPAddress Address { get; } public int Port { get; } public StandardizedEndPoint(IPAddress address, int port) { // 将IPv6映射的IPv4地址转换为纯IPv4格式 Address = address.IsIPv4MappedToIPv6 ? address.MapToIPv4() : address; Port = port; } public static StandardizedEndPoint FromEndPoint(EndPoint endPoint) { if (endPoint is not IPEndPoint ipEndPoint) throw new ArgumentException("仅支持IP端点类型", nameof(endPoint)); return new StandardizedEndPoint(ipEndPoint.Address, ipEndPoint.Port); } public bool Equals(StandardizedEndPoint other) { return Address.Equals(other.Address) && Port == other.Port; } public override bool Equals(object? obj) { return obj is StandardizedEndPoint other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(Address, Port); } public static bool operator ==(StandardizedEndPoint left, StandardizedEndPoint right) { return left.Equals(right); } public static bool operator !=(StandardizedEndPoint left, StandardizedEndPoint right) { return !left.Equals(right); } }
使用示例
// 假设已有活跃TcpClient实例tcpClient var clientLocal = StandardizedEndPoint.FromEndPoint(tcpClient.Client.LocalEndPoint!); var clientRemote = StandardizedEndPoint.FromEndPoint(tcpClient.Client.RemoteEndPoint!); IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties(); TcpConnectionInformation[] connections = properties.GetActiveTcpConnections(); // 查找匹配的TCP连接 var matchedConnection = connections.FirstOrDefault(conn => { var connLocal = StandardizedEndPoint.FromEndPoint(conn.LocalEndPoint); var connRemote = StandardizedEndPoint.FromEndPoint(conn.RemoteEndPoint); // 本地+远程端点完全匹配才视为同一个连接 return connLocal == clientLocal && connRemote == clientRemote; }); if (matchedConnection != null) { // 找到匹配连接,执行后续逻辑 }
方案2:简化的辅助对比方法(轻量场景)
如果不需要复用匹配逻辑,可以直接写一个静态方法完成对比:
public static bool AreEndPointsMatching(EndPoint a, EndPoint b) { if (a is not IPEndPoint ipA || b is not IPEndPoint ipB) return false; // 统一地址格式:IPv6映射地址转IPv4 var addrA = ipA.Address.IsIPv4MappedToIPv6 ? ipA.Address.MapToIPv4() : ipA.Address; var addrB = ipB.Address.IsIPv4MappedToIPv6 ? ipB.Address.MapToIPv4() : ipB.Address; // 对比IP地址和端口 return addrA.Equals(addrB) && ipA.Port == ipB.Port; }
使用示例
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties(); TcpConnectionInformation[] connections = properties.GetActiveTcpConnections(); var matchedConnection = connections.FirstOrDefault(conn => AreEndPointsMatching(conn.LocalEndPoint, tcpClient.Client.LocalEndPoint!) && AreEndPointsMatching(conn.RemoteEndPoint, tcpClient.Client.RemoteEndPoint!) );
兼容性说明
- 上述方法基于.NET标准库的
IsIPv4MappedToIPv6和MapToIPv4方法,支持.NET Framework 4.6+、.NET Core 2.0+、.NET 5+,跨Windows、Linux、macOS平台均有效。 - 转换逻辑仅处理IPv6映射的IPv4地址,不影响纯IPv6或纯IPv4地址的正常匹配。
内容的提问来源于stack exchange,提问作者joelc
相关产品推荐
相关产品推荐

