2016-04-30 16 views
1

Ich kam auf dieser CIDR zu berechnen, aber ich bin mir ziemlich sicher, dass es nicht der schnellste Weg ist:Erhalten CIDR von netmask

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 

Gibt es schneller Weg und wie wäre es mit IPv6?

+0

Der Algorithmus gut so für die Optimierung definiert ist, können Sie den Entscheidungscode-Bit-Operationen und abgerollt Loops erzeugen und zwischenzuspeichern. Dies könnte auf IPv4 oder IPv6 angewendet werden, der einzige Unterschied ist die Anzahl der Bytes. – Rbjz

Antwort

0

Sie können 10x-100x schneller erhalten, je nachdem, wie Sie mit ungültiger Netzmaske umgehen möchten, siehe - c code for valid netmask und https://superuser.com/questions/601252/is-225-225-225-128-a-valid-subnet-mask. Hier ist mein Benchmark-Ergebnis (wo Phantasie ist Ihr ursprünglicher Vorschlag, habe ich auch aus Neugier mit konstanter Zeit Ausführung experimentiert).

Lange Rede kurzer Sinn: arbeite in binär, benutze Konstanten, rolle deine Schleifen aus. Die Ultra Version könnte die beste sein. Bei ungültiger Netzmaske wird der nächste Wert zurückgegeben, der valid netmask enthält.

Wie wäre es nun mit IPv6? Wir haben vielleicht zu früh optimiert ... Ich hoffe niemand wagt es, die alte Netzmaskennotation für IPv6 zu verwenden. Es sollte vergessen werden.

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 } 

Und der Testcode:

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

Ihr ursprünglicher Code ist falsch - das GetHashCode() Ergebnis einer IP-Adresse wird Ihnen nichts über diese individuelle IP-Adresse sagen (oder lieber nicht).

In Anbetracht der Tatsache, dass eine Subnetzmaske mit CIDR-Notation einfach die Anzahl der Bits ist, die auf 1 gesetzt sind, können Sie dies am High-End mit Bit-Shift-Operatoren und dem binären AND-Operator relativ schnell berechnen.

+0

Code funktioniert gut. Zuerst wird die IP, die immer mit der Netzwerkmaske aufgerufen wird, in eine ganze Zahl umgewandelt, die dann in eine binäre Zeichenfolge umgewandelt wird, die in ein Zeichenarray umgewandelt wird. Dann berechne alle Zeichen, die '1' enthalten, aus diesem Char-Array und das gibt die richtige CIDR. Dein Kommentar "Dein ursprünglicher Code ist falsch" ist also falsch. – raspi

+1

@raspi 'ip.GetHashCode()' ist falsch. Es funktioniert nur zufällig und könnte jede neue Version von .NET Framework einbrechen. – yaakov

+0

Könnten Sie bitte einen Hinweis dafür geben? https://msdn.microsoft.com/en-us/library/system.net.ipaddress.gethashcode(v=vs.110).aspx sagt nichts über die Zukunft. – raspi