c# -如何识别列表中属于特定子网的IP地址

本文关键字:属于 子网 地址 IP 列表 何识别 识别 | 更新日期: 2023-09-27 18:08:32

我有一个大的动态IP地址列表,它们的子网掩码,以及一组给定的子网。我需要一些代码,以便能够识别每个地址所在的子网。我保持这个相当模糊,因为我对许多不同的解决方案持开放态度。有人能用c#编写类似的代码吗?谢谢!

c# -如何识别列表中属于特定子网的IP地址

首先,您需要代码将地址掩码到其子网:

public IPAddress ApplyMask(IPAddress address, IPAddress mask) {
    byte[] addressBytes = address.GetAddressBytes();
    byte[] maskBytes = mask.GetAddressBytes();
    var appliedMaskBytes =
        addressBytes.Zip(
            maskBytes,
            (addressByte, maskByte) => (byte)(addressByte & maskByte)
        )
        .ToArray();
    return new IPAddress(appliedMaskBytes);
}

然后,假设您有一个从IP地址到其掩码的Dictionary<IPAddress, IPAddress>:

IDictionary<IPAddress, IPAddress> maskDictionary;
var masked = ipAddresses
                 .Select(ipAddress => 
                     new { IPAddress = ipAddress,
                           Subnet = ApplyMask(
                               ipAddress,
                               maskDictionary[ipAddress]
                           )
                     }
                 )
                 .GroupBy(x => x.Subnet);

现在您有一个按子网划分的地址列表。因此。

(注意:我手边没有编译器。

您不需要子网列表—它们可以被推断出来。您可以使用一些按位计算:

// Key is {Subnet, Subnet Mask}.
// Value is list of IPs in that range.
public static IDictionary<Tuple<IPAddress, IPAddress>, ISet<IPAddress>> AllocateToSubnets(IEnumerable<Tuple<IPAddress, IPAddress>> ips)
{
    var dic = new Dictionary<Tuple<IPAddress, IPAddress>, ISet<IPAddress>>();
    foreach (var item in ips)
    {
        var subnet = Tuple.Create(GetSubnetAddress(item.Item1, item.Item2), item.Item2);
        ISet<IPAddress> set;
        if (!dic.TryGetValue(subnet, out set))
            dic.Add(subnet, set = new HashSet<IPAddress>());
        if (!set.Add(item.Item1))
        {
            // Throw an error if you are looking for duplicates.
        }
    }
    return dic;
}
private static IPAddress GetSubnetAddress(IPAddress address, IPAddress mask)
{
    var b1 = address.GetAddressBytes();
    var b2 = mask.GetAddressBytes();
    if (b1.Length != b2.Length)
        throw new InvalidOperationException("IPAddress and its mask do not share the same family.");
    for (var i = 0; i < b1.Length; i++)
        b1[i] &= b2[i];
    return new IPAddress(b1);
}

测试代码:

var ips = new[]
    {
        Tuple.Create(IPAddress.Parse("192.168.0.1"), IPAddress.Parse("255.255.255.0")),
        Tuple.Create(IPAddress.Parse("192.168.0.1"), IPAddress.Parse("255.255.0.0")),
        Tuple.Create(IPAddress.Parse("192.168.0.2"), IPAddress.Parse("255.255.255.0")),
        Tuple.Create(IPAddress.Parse("192.168.0.10"), IPAddress.Parse("255.255.255.0")),
        Tuple.Create(IPAddress.Parse("192.168.0.10"), IPAddress.Parse("255.255.0.0")),
        Tuple.Create(IPAddress.Parse("10.0.0.1"), IPAddress.Parse("255.255.255.0")),
        Tuple.Create(IPAddress.Parse("10.1.0.1"), IPAddress.Parse("255.255.0.0")),
        Tuple.Create(IPAddress.Parse("10.0.0.2"), IPAddress.Parse("255.255.255.0")),
        Tuple.Create(IPAddress.Parse("10.1.0.10"), IPAddress.Parse("255.255.255.0")),
        Tuple.Create(IPAddress.Parse("10.1.0.10"), IPAddress.Parse("255.255.0.0")),
    };
var subnets = AllocateToSubnets(ips);

这取决于您的子网的定义有哪些。如果它是一个IP地址范围,你可以使用:最简单的方法来检查IP地址的值范围使用c#

如果它是一个掩模,你可以使用ip&(~mask)来获得较低和ip|(~mask)来获得范围,并按照上面的方法进行。

如果子网给出了子网掩码的位数,你可以计算:mask=~(UInt32.MaxValue>>n)和使用按上述步骤进行

如果你想找出给定IP的网络掩码,那么我没有线索。