0

IP アドレス、それらのサブネット マスク、および特定のサブネット セットの大きな動的リストがあります。各アドレスがどのサブネット上にあるかを識別するためのコードが必要です。私は多くの異なる解決策を受け入れているので、これをかなりあいまいにしています。これに似たことができる C# のコードを持っている人はいますか? ありがとう!

4

3 に答える 3

2

まず、アドレスをそのサブネットにマスクするコードが必要です。

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);
}

Dictionary<IPAddress, IPAddress>次に、 IP アドレスからそのマスクまでがあると仮定します。

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

これで、サブネットごとのアドレスのリストができました。それに応じて進みます。

(注: 手元にコンパイラがありません。マイナーなコンパイラ エラーについては申し訳ありません。)

于 2011-09-13T14:18:29.770 に答える
1

サブネットのリストは必要ありません。推測できます。ビットごとの数学でそれを行うことができます:

// 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);
于 2011-09-13T14:30:54.937 に答える
0

これは、サブネットの定義にどちらがあるかによって異なります。使用できるIPアドレス範囲の場合:c#を使用して値の範囲に対してIPアドレスをチェックする最も簡単な方法

マスクの場合はip&(~mask)、下限ip|(~mask)を取得し、範囲を取得して上記のように進めるために使用できます。

サブネットにネットマスクのビット数が指定されている場合は、次のように計算できます mask=~(UInt32.MaxValue>>n)。上記の手順を使用します。

特定のIPのネットマスクを知りたい場合、私には手がかりがありません。IPv6についてもわかりません。

于 2011-09-13T14:13:53.420 に答える