【问题标题】:Get CIDR from netmask从网络掩码获取 CIDR
【发布时间】:2016-08-25 13:26:07
【问题描述】:

我想出这个来计算CIDR,但我很确定这不是最快的方法:

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

测试:

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

有更快的方法吗? IPv6 怎么样?

【问题讨论】:

  • 该算法定义良好,因此为了优化,您可以使用位操作和展开循环生成和缓存决策代码。这可以应用于 IPv4 或 IPv6,唯一的区别是字节数。

标签: c# cidr


【解决方案1】:

您的原始代码是错误的 - IP 地址的GetHashCode() 结果不会(或者更确切地说,不应该)告诉您有关该单个 IP 地址的任何信息。

考虑到 CIDR 表示法子网掩码只是设置为 1 的位数,从高端开始,您可以使用移位运算符和二进制 AND 运算符相当快速地计算。

【讨论】:

  • 代码工作正常。首先,总是使用网络掩码调用的 IP 转换为整数,然后转换为二进制字符串,再转换为字符数组。然后从该 char 数组中计算所有包含“1”的字符,并给出正确的 CIDR。所以您的评论“您的原始代码错误”是错误的。
  • @raspi 'ip.GetHashCode()' 是错误的。它只是偶然起作用,可能会在任何新版本的 .NET Framework 中中断。
  • 您能提供参考吗? msdn.microsoft.com/en-us/library/… 没说以后要破。
  • 好的,现在它使用 GetAddressBytes()
【解决方案2】:

我的 IPv4 解决方案

很简单:

int cidr = Convert.ToString(mask.Address, 2).Count( o => o == '1'); 

".Adress" 已弃用但仍受支持。

基于255.255.255.240的解释:

IPAddress mask = new IPAddress(new byte[] { 255, 255, 244, 240 });

// adressBinAsString = 11110000111101001111111111111111
string maskBinAsString = Convert.ToString(mask.Address, 2); 

// cidr = 28
int cidr = Convert.ToString(mask.Address, 2).Count( o=> o == '1'); // 

【讨论】:

    【解决方案3】:

    根据您希望如何处理无效网络掩码,您可以将速度提高 10 倍至 100 倍,请参阅 - c code for valid netmaskhttps://superuser.com/questions/601252/is-225-225-225-128-a-valid-subnet-mask。这是我的基准测试结果(您最初的建议很有趣,出于好奇,我也尝试了恒定时间执行)。

    长话短说:以二进制工作,使用常量,展开循环。 Ultra 版本可能是最好的。对于无效的网络掩码,它返回最接近的包含valid netmask

    现在IPv6 怎么样?我们可能已经过早地优化了……我希望没有人敢对 IPv6 使用老式的网络掩码表示法。它应该被遗忘。

    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 }
    

    以及测试代码:

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

    【讨论】:

      猜你喜欢
      • 2014-10-26
      • 1970-01-01
      • 2016-05-22
      • 2013-11-01
      • 2021-06-02
      • 2017-10-29
      • 1970-01-01
      • 2016-05-06
      • 2018-10-29
      相关资源
      最近更新 更多