【问题标题】:Deriving the Inverse of a subnet definition推导子网定义的逆
【发布时间】:2010-11-07 21:22:32
【问题描述】:

一个 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

我对可能被称为子网逆的东西感兴趣
是这样描述的,

对于给定的 SubnetA(例如 NetworkA / MaskA),
SubnetA 的倒数是 k 个子网的列表,这样,

如果 IP 地址 A 匹配 SubnetA
A 将不匹配其中任何一个 k 子网和
每个与 SubnetA 不匹配的 IP 地址 B
将完全匹配这些 k 个子网中的 1 个。

代码不是必需的,我对正确和最佳的方法感兴趣。


我在下面记录了优化的答案以供参考,因此它不会分散人们尝试此问题的注意力。一直接受 Rafał 的回答,因为他也先做对了。

【问题讨论】:

    标签: algorithm ip-address subnet


    【解决方案1】:

    我已在此代码 sn-p 中注明了供参考的优化答案。

    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
    

    【讨论】:

      【解决方案2】:

      如果您想象从0.0.0.0/32 开始的所有子网的树,在每一位都有分支,那么您需要所有不通向您的子网的分支。您上一步(位),将此位清空并将该节点的兄弟(在适当的位置具有不同的位)添加到您的集合中。 (和 Rafał 说的一样,只是表达方式不同。)你可以这样做(工作 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

      编辑:我意识到这里绝对不需要递归。函数式编程似乎有时会导致错误的想法。

      【讨论】:

        【解决方案3】:

        A 中的每个未屏蔽位 b 一个子网,匹配 A 中的所有先前位,与 b 不同,屏蔽所有后续位。这样,不在A 中的每个地址i 将只匹配上述网络中的一个,即负责i 的第一位与A 不匹配的网络。

        【讨论】:

          【解决方案4】:

          嗯。我会说它基本上是除 A 之外的任何子网,具有相同的掩码......

          【讨论】:

          • 你枚举了 192.168.0.0/16 吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-07
          • 2019-10-01
          • 1970-01-01
          • 2019-07-25
          相关资源
          最近更新 更多