7

IP アドレス範囲 (CIDR 表記) があり、任意の IP アドレスがその範囲内にあるかどうかを知る必要がある場合 (両方とも文字列として表示)、C# でこれを行う最も簡単な方法は何ですか?

例:

  • IPv4 範囲: 192.168.168.100/24、確認する IP:192.168.168.200
  • IPv6 範囲: fe80::202:b3ff:fe1e:8329/24、確認する IP:2001:db8::
4

3 に答える 3

12

簡単なクラスを次に示します。

public class IPSubnet
{
    private readonly byte[] _address;
    private readonly int _prefixLength;

    public IPSubnet(string value)
    {
        if (value == null)
            throw new ArgumentNullException("value");

        string[] parts = value.Split('/');
        if (parts.Length != 2)
            throw new ArgumentException("Invalid CIDR notation.", "value");

        _address = IPAddress.Parse(parts[0]).GetAddressBytes();
        _prefixLength = Convert.ToInt32(parts[1], 10);
    }

    public bool Contains(string address)
    {
        return this.Contains(IPAddress.Parse(address).GetAddressBytes());
    }

    public bool Contains(byte[] address)
    {
        if (address == null)
            throw new ArgumentNullException("address");

        if (address.Length != _address.Length)
            return false; // IPv4/IPv6 mismatch

        int index = 0;
        int bits = _prefixLength;

        for (; bits >= 8; bits -= 8)
        {
            if (address[index] != _address[index])
                return false;
            ++index;
        }

        if (bits > 0)
        {
            int mask = (byte)~(255 >> bits);
            if ((address[index] & mask) != (_address[index] & mask))
                return false;
        }

        return true;
    }
}

使用例:

Console.WriteLine(new IPSubnet("192.168.168.100/24").Contains("192.168.168.200")); // True
Console.WriteLine(new IPSubnet("fe80::202:b3ff:fe1e:8329/24").Contains("2001:db8::")); // False

このクラスは、すべての IPv4 アドレスをすべての IPv6 アドレスとは異なるものとして扱い、IPv4 と IPv6 の間で変換を試みません。

于 2012-05-10T03:33:19.477 に答える