You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何跨平台匹配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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:50:24