Get CIDR from netmask

こ雲淡風輕ζ 提交于 2019-12-13 01:24:26

问题


I came up with this to calculate CIDR but I'm pretty sure that it isn't the most fastest way:

public int MaskToCIDR(IPAddress ip)
{
  return Convert
         .ToString(BitConverter.ToInt32(ip.GetAddressBytes(), 0), 2)
         .ToCharArray()
         .Count(x => x == '1');
}

Test:

Console.WriteLine(MaskToCIDR(new IPAddress(new byte[]{255,255,255,255}))); // 32
Console.WriteLine(MaskToCIDR(new IPAddress(new byte[]{255,255,255,0}))); // 24
Console.WriteLine(MaskToCIDR(new IPAddress(new byte[]{255,255,0,0}))); // 16
Console.WriteLine(MaskToCIDR(new IPAddress(new byte[]{255,0,0,0}))); // 8
Console.WriteLine(MaskToCIDR(new IPAddress(new byte[]{0,0,0,0}))); // 0

Is there faster way and how about IPv6?


回答1:


You can get 10x-100x faster depending on how you want to handle invalid netmask see - c code for valid netmask and https://superuser.com/questions/601252/is-225-225-225-128-a-valid-subnet-mask. Here's my benchmark result (where fancy is your original proposal, I have experimented with constant time execution out of curiosity as well).

Long story short: work in binary, use constants, unroll your loops. The Ultra version might be the best. For invalid netmask it returns the closest containing valid netmask.

Now how about IPv6? We may have prematurely optimized... I hope nobody dares to use the old-style netmask notation for IPv6. It should be forgotten.

11111111.11111111.11111111.11111111 (255.255.255.255)
{ ns =    625,574, cidrnet = 32, method = MaskToCIDR_Fancy }
{ ns =     61,136, cidrnet = 32, method = MaskToCIDR_Fast }
{ ns =     72,039, cidrnet = 32, method = MaskToCIDR_Constant }
{ ns =      4,710, cidrnet = 32, method = MaskToCIDR_Ultra }
{ ns =     14,250, cidrnet = 32, method = MaskToCIDR_ConstantUltra }
{ ns =      8,683, cidrnet = 32, method = MaskToCIDR_Mambo }
{ ns =      7,337, cidrnet = 32, method = MaskToCIDR_PerByte }
{ ns =     37,883, cidrnet = 32, method = MaskToCIDR_BTree }
{ ns =      2,127, cidrnet = 0, method = MaskToCIDR_Empty }

11111111.11111111.11111111.00000000 (255.255.255.0)
{ ns =    486,026, cidrnet = 24, method = MaskToCIDR_Fancy }
{ ns =     47,369, cidrnet = 24, method = MaskToCIDR_Fast }
{ ns =     69,921, cidrnet = 24, method = MaskToCIDR_Constant }
{ ns =      4,835, cidrnet = 24, method = MaskToCIDR_Ultra }
{ ns =     14,079, cidrnet = 24, method = MaskToCIDR_ConstantUltra }
{ ns =      6,663, cidrnet = 24, method = MaskToCIDR_Mambo }
{ ns =      7,336, cidrnet = 24, method = MaskToCIDR_PerByte }
{ ns =     24,911, cidrnet = 24, method = MaskToCIDR_BTree }
{ ns =      2,116, cidrnet = 0, method = MaskToCIDR_Empty }

11111111.11111111.11111110.00000000 (255.255.254.0)
{ ns =    482,456, cidrnet = 23, method = MaskToCIDR_Fancy }
{ ns =     45,700, cidrnet = 23, method = MaskToCIDR_Fast }
{ ns =     68,930, cidrnet = 23, method = MaskToCIDR_Constant }
{ ns =      4,791, cidrnet = 23, method = MaskToCIDR_Ultra }
{ ns =     14,036, cidrnet = 23, method = MaskToCIDR_ConstantUltra }
{ ns =      6,951, cidrnet = 23, method = MaskToCIDR_Mambo }
{ ns =      7,377, cidrnet = 23, method = MaskToCIDR_PerByte }
{ ns =     36,027, cidrnet = 23, method = MaskToCIDR_BTree }
{ ns =      2,115, cidrnet = 0, method = MaskToCIDR_Empty }

11111111.11111111.00000000.00000000 (255.255.0.0)
{ ns =    347,425, cidrnet = 16, method = MaskToCIDR_Fancy }
{ ns =     34,460, cidrnet = 16, method = MaskToCIDR_Fast }
{ ns =     67,445, cidrnet = 16, method = MaskToCIDR_Constant }
{ ns =      4,942, cidrnet = 16, method = MaskToCIDR_Ultra }
{ ns =     15,363, cidrnet = 16, method = MaskToCIDR_ConstantUltra }
{ ns =      6,164, cidrnet = 16, method = MaskToCIDR_Mambo }
{ ns =      7,929, cidrnet = 16, method = MaskToCIDR_PerByte }
{ ns =     22,312, cidrnet = 16, method = MaskToCIDR_BTree }
{ ns =      2,116, cidrnet = 0, method = MaskToCIDR_Empty }

11111111.00000000.00000000.00000000 (255.0.0.0)
{ ns =    198,180, cidrnet = 8, method = MaskToCIDR_Fancy }
{ ns =     20,683, cidrnet = 8, method = MaskToCIDR_Fast }
{ ns =     64,785, cidrnet = 8, method = MaskToCIDR_Constant }
{ ns =      5,138, cidrnet = 8, method = MaskToCIDR_Ultra }
{ ns =     14,058, cidrnet = 8, method = MaskToCIDR_ConstantUltra }
{ ns =      6,734, cidrnet = 8, method = MaskToCIDR_Mambo }
{ ns =      8,572, cidrnet = 8, method = MaskToCIDR_PerByte }
{ ns =     37,483, cidrnet = 8, method = MaskToCIDR_BTree }
{ ns =      2,253, cidrnet = 0, method = MaskToCIDR_Empty }

10000000.00000000.00000000.00000000 (128.0.0.0)
{ ns =    198,620, cidrnet = 1, method = MaskToCIDR_Fancy }
{ ns =      7,855, cidrnet = 1, method = MaskToCIDR_Fast }
{ ns =     62,570, cidrnet = 1, method = MaskToCIDR_Constant }
{ ns =      6,317, cidrnet = 1, method = MaskToCIDR_Ultra }
{ ns =     14,145, cidrnet = 1, method = MaskToCIDR_ConstantUltra }
{ ns =      6,399, cidrnet = 1, method = MaskToCIDR_Mambo }
{ ns =      7,413, cidrnet = 1, method = MaskToCIDR_PerByte }
{ ns =     33,861, cidrnet = 1, method = MaskToCIDR_BTree }
{ ns =      2,117, cidrnet = 0, method = MaskToCIDR_Empty }

00000000.00000000.00000000.00000000 (0.0.0.0)
{ ns =     83,629, cidrnet = 0, method = MaskToCIDR_Fancy }
{ ns =      7,348, cidrnet = 0, method = MaskToCIDR_Fast }
{ ns =     63,320, cidrnet = 0, method = MaskToCIDR_Constant }
{ ns =      4,639, cidrnet = 0, method = MaskToCIDR_Ultra }
{ ns =     14,284, cidrnet = 0, method = MaskToCIDR_ConstantUltra }
{ ns =      5,438, cidrnet = 0, method = MaskToCIDR_Mambo }
{ ns =      6,767, cidrnet = 0, method = MaskToCIDR_PerByte }
{ ns =     37,961, cidrnet = 0, method = MaskToCIDR_BTree }
{ ns =      2,118, cidrnet = 0, method = MaskToCIDR_Empty }

01101111.01101111.01101111.00000000 (111.111.111.0)
{ ns =    465,689, cidrnet = 18, method = MaskToCIDR_Fancy }
{ ns =      4,242, cidrnet = -1, method = MaskToCIDR_Fast }
{ ns =     67,996, cidrnet = -1, method = MaskToCIDR_Constant }
{ ns =      5,133, cidrnet = 24, method = MaskToCIDR_Ultra }
{ ns =     14,542, cidrnet = 18, method = MaskToCIDR_ConstantUltra }
{ ns =      6,285, cidrnet = -1, method = MaskToCIDR_Mambo }
{ ns =      7,879, cidrnet = -21, method = MaskToCIDR_PerByte }
{ ns =     40,017, cidrnet = -2, method = MaskToCIDR_BTree }
{ ns =      2,115, cidrnet = 0, method = MaskToCIDR_Empty }

00000001.00000001.00000001.00000000 (1.1.1.0)
{ ns =    368,824, cidrnet = 3, method = MaskToCIDR_Fancy }
{ ns =      4,227, cidrnet = -1, method = MaskToCIDR_Fast }
{ ns =     67,043, cidrnet = -1, method = MaskToCIDR_Constant }
{ ns =      4,920, cidrnet = 24, method = MaskToCIDR_Ultra }
{ ns =     13,979, cidrnet = 3, method = MaskToCIDR_ConstantUltra }
{ ns =      6,134, cidrnet = -1, method = MaskToCIDR_Mambo }
{ ns =      7,611, cidrnet = -24, method = MaskToCIDR_PerByte }
{ ns =     39,957, cidrnet = -2, method = MaskToCIDR_BTree }
{ ns =      2,115, cidrnet = 0, method = MaskToCIDR_Empty }

And the test code:

public class CalculateCIDRProgram
{
    private static uint[] dic = Enumerable.Range(0, 33).Select(i => i == 0 ? 0 : (uint)(~(1 << (32 - i)) + 1)).ToArray();

    private static Stopwatch __watch;

    public static void Main()
    {
        for (int i = 0; i < 33; i++)
        {
            byte[] intBytes = BitConverter.GetBytes(dic[i]);
            if (BitConverter.IsLittleEndian)
                Array.Reverse(intBytes);
            Console.WriteLine($"{i}: {FormatBytes(intBytes)}");
        }

        __watch = Stopwatch.StartNew();
        Test(IPAddress.Parse("255.255.255.255"));
        Test(IPAddress.Parse("255.255.255.0"));
        Test(IPAddress.Parse("255.255.254.0"));
        Test(IPAddress.Parse("255.255.0.0"));
        Test(IPAddress.Parse("255.0.0.0"));
        Test(IPAddress.Parse("128.0.0.0"));
        Test(IPAddress.Parse("0.0.0.0"));
        Test(IPAddress.Parse("1.1.1.0"));
        Test(IPAddress.Parse("111.111.111.0"));
    }

    private static void Test(IPAddress ip)
    {

        WriteHeader(ip);

        var ipbytes = ip.GetAddressBytes();
        var loops = 1000000;
        //var loops = 1;
        var cidrnet = null as int?;
        var results = new List<object>();

        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_Fancy(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_Fancy) });

        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_Fast(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_Fast) });

        fakeBool = true;
        fakeInt = new Random().Next(33);
        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_Constant(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_Constant) });

        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_Ultra(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_Ultra) });

        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_ConstantUltra(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_ConstantUltra) });

        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_Mambo(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_Mambo) });

        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_PerByte(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_PerByte) });

        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_BTree(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_BTree) });

        __watch.Restart();
        for (int i = 0; i < loops; i++)
            cidrnet = MaskToCIDR_Empty(ipbytes);
        results.Add(new { ns = (1000000 * __watch.Elapsed.TotalMilliseconds / loops).ToString("0.000").PadLeft(10, ' '), cidrnet, method = nameof(MaskToCIDR_Empty) });

        foreach (var result in results)
        {
            Console.WriteLine(result);
        }

        Console.WriteLine();
    }

    private static int fakeInt;
    private static bool fakeBool;

    private static int MaskToCIDR_Empty(byte[] bytes)
    {
        return 0;
    }
    private static int MaskToCIDR_BTree(byte[] bytes)
    {
        var addr = (uint)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);

        return Array.BinarySearch(dic, addr);
    }

    private static int MaskToCIDR_PerByte(byte[] bytes)
    {
        int b0 = bytes[0];
        int b1 = bytes[1];
        int b2 = bytes[2];
        int b3 = bytes[3];

        switch (b3)
        {
            case 0x00: break;
            case 0xFF: return 32;
            case 0xFE: return 31;
            case 0xFC: return 30;
            case 0xF8: return 29;
            case 0xF0: return 28;
            case 0xE0: return 27;
            case 0xC0: return 26;
            case 0x80: return 25;
            default:
                return ~(
           (b3 & 0x01) == 0 ? 32 :
           (b3 & 0x02) == 0 ? 31 :
           (b3 & 0x04) == 0 ? 30 :
           (b3 & 0x08) == 0 ? 29 :
           (b3 & 0x10) == 0 ? 28 :
           (b3 & 0x20) == 0 ? 27 :
           (b3 & 0x40) == 0 ? 26 :
                              25
           );
        }

        switch (b2)
        {
            case 0x00: break;
            case 0xFF: return 24;
            case 0xFE: return 23;
            case 0xFC: return 22;
            case 0xF8: return 21;
            case 0xF0: return 20;
            case 0xE0: return 19;
            case 0xC0: return 18;
            case 0x80: return 17;
            default:
                return ~(
           (b2 & 0x01) == 0 ? 24 :
           (b2 & 0x02) == 0 ? 23 :
           (b2 & 0x04) == 0 ? 22 :
           (b2 & 0x08) == 0 ? 21 :
           (b2 & 0x10) == 0 ? 20 :
           (b2 & 0x20) == 0 ? 19 :
           (b2 & 0x40) == 0 ? 18 :
                              17
           );
        }

        switch (b1)
        {
            case 0x00: break;
            case 0xFF: return 16;
            case 0xFE: return 15;
            case 0xFC: return 14;
            case 0xF8: return 13;
            case 0xF0: return 12;
            case 0xE0: return 11;
            case 0xC0: return 10;
            case 0x80: return 9;
            default:
                return ~(
           (b1 & 0x01) == 0 ? 16 :
           (b1 & 0x02) == 0 ? 15 :
           (b1 & 0x04) == 0 ? 14 :
           (b1 & 0x08) == 0 ? 13 :
           (b1 & 0x10) == 0 ? 12 :
           (b1 & 0x20) == 0 ? 11 :
           (b1 & 0x40) == 0 ? 10 :
                              9
           );
        }

        switch (b0)
        {
            case 0x00: break;
            case 0xFF: return 8;
            case 0xFE: return 7;
            case 0xFC: return 6;
            case 0xF8: return 5;
            case 0xF0: return 4;
            case 0xE0: return 3;
            case 0xC0: return 2;
            case 0x80: return 1;
            default:
                return ~(
           (b0 & 0x01) == 0 ? 8 :
           (b0 & 0x02) == 0 ? 7 :
           (b0 & 0x04) == 0 ? 6 :
           (b0 & 0x08) == 0 ? 5 :
           (b0 & 0x10) == 0 ? 4 :
           (b0 & 0x20) == 0 ? 3 :
           (b0 & 0x40) == 0 ? 2 :
                              1
           );
        }

        return 0;
    }

    private static int MaskToCIDR_Mambo(byte[] bytes)
    {
        var addr = (uint)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);

        switch (addr)
        {
            case 0xFFFFFFFF: return 32;
            case 0xFFFFFFFE: return 31;
            case 0xFFFFFFFC: return 30;
            case 0xFFFFFFF8: return 29;
            case 0xFFFFFFF0: return 28;
            case 0xFFFFFFE0: return 27;
            case 0xFFFFFFC0: return 26;
            case 0xFFFFFF80: return 25;
            case 0xFFFFFF00: return 24;
            case 0xFFFFFE00: return 23;
            case 0xFFFFFC00: return 22;
            case 0xFFFFF800: return 21;
            case 0xFFFFF000: return 20;
            case 0xFFFFE000: return 19;
            case 0xFFFFC000: return 18;
            case 0xFFFF8000: return 17;
            case 0xFFFF0000: return 16;
            case 0xFFFE0000: return 15;
            case 0xFFFC0000: return 14;
            case 0xFFF80000: return 13;
            case 0xFFF00000: return 12;
            case 0xFFE00000: return 11;
            case 0xFFC00000: return 10;
            case 0xFF800000: return 9;
            case 0xFF000000: return 8;
            case 0xFE000000: return 7;
            case 0xFC000000: return 6;
            case 0xF8000000: return 5;
            case 0xF0000000: return 4;
            case 0xE0000000: return 3;
            case 0xC0000000: return 2;
            case 0x80000000: return 1;
            case 0x00000000: return 0;
            default:
                return ~(
                    (addr & 0x80000000) == 0 ? 0 :
                    (addr & 0x40000000) == 0 ? 1 :
                    (addr & 0x20000000) == 0 ? 2 :
                    (addr & 0x10000000) == 0 ? 3 :
                    (addr & 0x08000000) == 0 ? 4 :
                    (addr & 0x04000000) == 0 ? 5 :
                    (addr & 0x02000000) == 0 ? 6 :
                    (addr & 0x01000000) == 0 ? 7 :
                    (addr & 0x00800000) == 0 ? 8 :
                    (addr & 0x00400000) == 0 ? 9 :
                    (addr & 0x00200000) == 0 ? 10 :
                    (addr & 0x00100000) == 0 ? 11 :
                    (addr & 0x00080000) == 0 ? 12 :
                    (addr & 0x00040000) == 0 ? 13 :
                    (addr & 0x00020000) == 0 ? 14 :
                    (addr & 0x00010000) == 0 ? 15 :
                    (addr & 0x00008000) == 0 ? 16 :
                    (addr & 0x00004000) == 0 ? 17 :
                    (addr & 0x00002000) == 0 ? 18 :
                    (addr & 0x00001000) == 0 ? 19 :
                    (addr & 0x00000800) == 0 ? 20 :
                    (addr & 0x00000400) == 0 ? 21 :
                    (addr & 0x00000200) == 0 ? 22 :
                    (addr & 0x00000100) == 0 ? 23 :
                    (addr & 0x00000080) == 0 ? 24 :
                    (addr & 0x00000040) == 0 ? 25 :
                    (addr & 0x00000020) == 0 ? 26 :
                    (addr & 0x00000010) == 0 ? 27 :
                    (addr & 0x00000008) == 0 ? 28 :
                    (addr & 0x00000004) == 0 ? 29 :
                    (addr & 0x00000002) == 0 ? 30 :
                    (addr & 0x00000001) == 0 ? 31 :
                    32);
        }
    }

    private static int MaskToCIDR_ConstantUltra(byte[] bytes)
    {
        var b0 = bytes[0];
        var b1 = bytes[1];
        var b2 = bytes[2];
        var b3 = bytes[3];

        var result =
           ((b0 & 0x80) >> 7) +
           ((b0 & 0x40) >> 6) +
           ((b0 & 0x20) >> 5) +
           ((b0 & 0x10) >> 4) +
           ((b0 & 0x08) >> 3) +
           ((b0 & 0x04) >> 2) +
           ((b0 & 0x02) >> 1) +
            (b0 & 0x01) +
           ((b1 & 0x80) >> 7) +
           ((b1 & 0x40) >> 6) +
           ((b1 & 0x20) >> 5) +
           ((b1 & 0x10) >> 4) +
           ((b1 & 0x08) >> 3) +
           ((b1 & 0x04) >> 2) +
           ((b1 & 0x02) >> 1) +
            (b1 & 0x01) +
           ((b2 & 0x80) >> 7) +
           ((b2 & 0x40) >> 6) +
           ((b2 & 0x20) >> 5) +
           ((b2 & 0x10) >> 4) +
           ((b2 & 0x08) >> 3) +
           ((b2 & 0x04) >> 2) +
           ((b2 & 0x02) >> 1) +
            (b2 & 0x01) +
           ((b3 & 0x80) >> 7) +
           ((b3 & 0x40) >> 6) +
           ((b3 & 0x20) >> 5) +
           ((b3 & 0x10) >> 4) +
           ((b3 & 0x08) >> 3) +
           ((b3 & 0x04) >> 2) +
           ((b3 & 0x02) >> 1) +
            (b3 & 0x01)
            ;

        return result;
    }


    private static int MaskToCIDR_Ultra(byte[] bytes)
    {
        var b0 = bytes[0];
        var b1 = bytes[1];
        var b2 = bytes[2];
        var b3 = bytes[3];

        return
            b3 != 0 ? (
                (b3 & 0x01) != 0 ? 32 :
                (b3 & 0x02) != 0 ? 31 :
                (b3 & 0x04) != 0 ? 30 :
                (b3 & 0x08) != 0 ? 29 :
                (b3 & 0x10) != 0 ? 28 :
                (b3 & 0x20) != 0 ? 27 :
                (b3 & 0x40) != 0 ? 26 :
                                   25) :
            b2 != 0 ? (
                (b2 & 0x01) != 0 ? 24 :
                (b2 & 0x02) != 0 ? 23 :
                (b2 & 0x04) != 0 ? 22 :
                (b2 & 0x08) != 0 ? 21 :
                (b2 & 0x10) != 0 ? 20 :
                (b2 & 0x20) != 0 ? 19 :
                (b2 & 0x40) != 0 ? 18 :
                                   17) :
            b1 != 0 ? (
                (b1 & 0x01) != 0 ? 16 :
                (b1 & 0x02) != 0 ? 15 :
                (b1 & 0x04) != 0 ? 14 :
                (b1 & 0x08) != 0 ? 13 :
                (b1 & 0x10) != 0 ? 12 :
                (b1 & 0x20) != 0 ? 11 :
                (b1 & 0x40) != 0 ? 10 :
                                   9) :
            b0 != 0 ? (
                (b0 & 0x01) != 0 ? 8 :
                (b0 & 0x02) != 0 ? 7 :
                (b0 & 0x04) != 0 ? 6 :
                (b0 & 0x08) != 0 ? 5 :
                (b0 & 0x10) != 0 ? 4 :
                (b0 & 0x20) != 0 ? 3 :
                (b0 & 0x40) != 0 ? 2 :
                                   1) :
                               0;
    }

    private static int MaskToCIDR_Constant(byte[] bytes)
    {
        int cidrnet = 0;
        var done = false;
        var invalid = false;

        for (var i = 0; i < bytes.Length; i++)
        {
            for (int v = bytes[i], j = 0; j < 8; v = v << 1, j++)
            {
                if ((v & 0x80) == 0)
                {
                    fakeBool = done;
                    done = true;
                    if (fakeBool)
                        fakeInt++;
                    else
                        fakeInt++;
                }
                else
                {
                    invalid = done;
                    fakeBool = true;
                    if (done)
                        fakeInt++;
                    else
                        cidrnet++;
                }
            }
        }

        if (invalid)
            cidrnet = ~cidrnet;
        else
            fakeInt = ~fakeInt;

        return cidrnet;
    }

    private static int MaskToCIDR_Fast(byte[] bytes)
    {
        int cidrnet = 0;
        var zeroed = false;
        for (var i = 0; i < bytes.Length; i++)
        {
            for (int v = bytes[i]; (v & 0xFF) != 0; v = v << 1)
            {
                if (zeroed)
                    // invalid netmask
                    return ~cidrnet;

                if ((v & 0x80) == 0)
                    zeroed = true;
                else
                    cidrnet++;
            }
        }
        return cidrnet;
    }

    private static int MaskToCIDR_Fancy(byte[] bytes)
    {
        return Convert
               .ToString(BitConverter.ToInt32(bytes, 0), 2)
               .ToCharArray()
               .Count(x => x == '1');
    }

    private static void WriteHeader(IPAddress ip)
    {
        var binIp = FormatBytes(ip.GetAddressBytes());
        Console.WriteLine($"{binIp} ({ip})");
    }
    private static string FormatBytes(byte[] bytes)
    {
        return string.Join(".", bytes.Select(b => Convert.ToString(b, 2).PadLeft(8, '0')));
    }
}



回答2:


Your original code is wrong - the GetHashCode() result of an IP Address won't (or rather, shouldn't) tell you anything about that individual IP address.

Considering that a CIDR-notation subnet mask is simply the number of bits that are set to 1, starting at the high end, you can calculate that rather quickly using bit-shift operators and the binary AND operator.



来源:https://stackoverflow.com/questions/36954345/get-cidr-from-netmask

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!