代码之家  ›  专栏  ›  技术社区  ›  nik

求子网定义的逆

  •  0
  • nik  · 技术社区  · 15 年前

    IP子网由两部分定义:网络和前缀长度或掩码。
    例如 192.168.0.0/16 (或) 192.168.0.0/255.255.0.0 )

    像这样的IP地址 192.168.1.1 据说与此子网匹配,因为,

    (192.168.1.1 & 255.255.0.0) == 192.168.0.0
    

    我对所谓的子网反向感兴趣
    就像这样描述的,

    对于给定的 子网 (比如,networka/maska)
    子网 是名单 K 子网,这样,

    如果IP地址 火柴 子网 ,
    与这些都不匹配 K 子网,以及
    每个IP地址 不匹配的 子网 ,
    完全匹配 这些 K 子网。

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


    我在下面列出了优化的答案以供参考,因此它不会分散人们将此作为问题的注意力。自从拉法_

    4 回复  |  直到 11 年前
        1
  •  2
  •   Rafał Dowgird    15 年前

    每个未屏蔽位有一个子网 b 在里面 A ,匹配中的所有前位 不同的 ,屏蔽以下所有位。这样每个地址 i 歪投球 只匹配上述网络中的一个,即负责 不匹配的 .

        2
  •  0
  •   Lucero    15 年前

    嗯,我想说,它基本上是除具有相同掩码的子网之外的任何子网…

        3
  •  0
  •   svick bala    15 年前

    如果你想象所有子网的树从 0.0.0.0/32 ,在每一位进行分支,您需要所有不通向子网的分支。向上一步(位),将该位置空,并将该节点的同级(在适当的位置上具有不同的位)添加到集合中。(和rafa_所说的一样,只是表达方式不同。)你可以这样做(工作代码):

    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 .

    编辑:我意识到递归在这里是绝对不必要的。似乎函数式编程有时会导致错误的思考。

        4
  •  0
  •   nik    11 年前

    我在这段代码中记录了优化的答案以供参考。

    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
    

    接受了拉法的回答,因为他也先答对了。


    这里是 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