2009-07-03 40 views
0

IP子網由兩部分定義,網絡和前綴長度或掩碼。
例如192.168.0.0/16(或192.168.0.0/255.255.0.0)。導出子網定義的反轉

192.168.1.1

的IP地址是說,因爲

(192.168.1.1 & 255.255.0.0) == 192.168.0.0 

我感興趣的可以稱之爲這是這樣描述的子網
的倒數到該子網匹配,

對於給定的子網A(比方說NetworkA/MaskA),
的倒數子網A是t他的ķ子網,這樣,

如果一個IP地址一個,匹配SUBNETA
一個將不匹配任何這些ķ子網,並
每個IP地址列表不匹配SUBNETA
將完全匹配這些ķ蘇bnets。

代碼不是必需的,我對正確和最佳的方法感興趣。


我有以下參考的優化答案,因此它不會分散人們試圖將其作爲一個問題。由於他也是第一個正確答案,所以保留接受Rafał的回答。

回答

2

一個子網中的所有以下位。這樣,每個地址i不在A將只匹配上述網絡之一,即負責i的第一位,不匹配A

0

嗯。我會說,它基本上是一比用相同的掩模其他任何子網...

爲每東窗事發位 bA,以前所有的位匹配 A,不同的 b,屏蔽
+0

您是否列舉了192.168.0.0/16? – nik 2009-07-03 09:40:53

0

如果你想象所有子網的樹都從0.0.0.0/32開始,在每一位都分支,你想要所有不通向你的子網的分支。你上升一步(位),將此位置爲空,並將此節點的兄弟(在適當的位置有不同的位)添加到你的集合中。 (這是一樣的拉法爾說,只是表達方式不同。)你可以像下面這樣做(工作C#代碼):

using System; 
using System.Text; 

namespace so_subnet_complement 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Enter subnet in the 192.168.0.0/16 format."); 
      string[] line = Console.ReadLine().Split('/'); 
      string[] segments = line[0].Split('.'); 
      uint ip = 0; 
      uint multiplier = 1; 
      for (int i = 3; i >= 0; i--) 
      { 
       ip += byte.Parse(segments[i]) * multiplier; 
       multiplier *= 0x100; 
      } 
      int mask = int.Parse(line[1]); 

      Console.WriteLine("Complement subnets:"); 
      writeComplementSubnets(ip, mask); 
     } 

     static void writeComplementSubnets(uint ip, int mask) 
     { 
      for (;mask < 32; mask++) 
      { 
       uint newIp =(uint)(ip & (0xFFFFFFFF << mask)^(1 << mask)); 
       Console.WriteLine("{0}/{1}", ipToString(newIp), mask); 
      } 
     } 

     static string ipToString(uint ip) 
     { 
      StringBuilder result = new StringBuilder(15); 
      uint mask = 0xFF000000; 
      int shift = 24; 
      for (int i = 0; i < 4; i++) 
      { 
       result.Append((ip & mask) >> shift); 
       mask >>= 8; 
       shift -= 8; 
       if (i < 3) 
        result.Append('.'); 
      } 
      return result.ToString(); 
     } 
    } 
} 

最重要的是writeComplementSubnets方法。 IP地址以自然(代表)表示,因此192.168.0.0變爲0xC0A80000

編輯:我意識到遞歸在這裏絕對是不必要的。看來功能性編程有時會導致錯誤的思考。

0

我有在此代碼段中提到的優化答案供參考。

unsigned int network; // 32-bit network. Say (192.168.0.0 or 0xC0A80000) 
unsigned int mask; // 32-bit mask (0xFFFF0000 for the example case) 

i = 0; // to iterate over the network bits 
do { 
    bitmask = (unsigned int)(0x80000000 >> i) 
    invmask = (unsigned int)(0xFFFFFFFF << (31-i)); 

    invnet = (invmask & network)^bitmask; 
    printSubnet(invnet, invmask); // this stores/prints the subnet 

} while (mask && i<32); // only while we have valid mask 

接受Rafał的回答,因爲他也把它對準了。


這裏是192.168.0.0/16的逆,以檢查正確性。

[1] 0.0.0.0/128.0.0.0   ; 00000000 
[2] 128.0.0.0/192.0.0.0  ; 80000000 
[3] 224.0.0.0/224.0.0.0  ; e0000000 
[4] 208.0.0.0/240.0.0.0  ; d0000000 
[5] 200.0.0.0/248.0.0.0  ; c8000000 
[6] 196.0.0.0/252.0.0.0  ; c4000000 
[7] 194.0.0.0/254.0.0.0  ; c2000000 
[8] 193.0.0.0/255.0.0.0  ; c1000000 
[9] 192.0.0.0/255.128.0.0  ; c0000000 
[10] 192.192.0.0/255.192.0.0 ; c0c00000 
[11] 192.128.0.0/255.224.0.0 ; c0800000 
[12] 192.176.0.0/255.240.0.0 ; c0b00000 
[13] 192.160.0.0/255.248.0.0 ; c0a00000 
[14] 192.172.0.0/255.252.0.0 ; c0ac0000 
[15] 192.170.0.0/255.254.0.0 ; c0aa0000 
[16] 192.169.0.0/255.255.0.0 ; c0a90000