Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何获取不在给定IP地址范围内的所有IP地址_Algorithm_Network Programming_Ip_Salesforce_Apex - Fatal编程技术网

Algorithm 如何获取不在给定IP地址范围内的所有IP地址

Algorithm 如何获取不在给定IP地址范围内的所有IP地址,algorithm,network-programming,ip,salesforce,apex,Algorithm,Network Programming,Ip,Salesforce,Apex,我需要能够输出不在给定IP地址范围列表中的所有IP地址范围 我可以使用某种算法来完成这类任务,并将其转换为工作代码 基本上,我将使用Salesforce Apex代码,因此,如果给定的示例可行,任何类似JAVA的语言都可以 首先,我假设您的意思是您获得一个或多个不相交的CIDR范围作为输入,并且需要生成所有CIDR范围的列表,其中不包括任何作为输入的CIDR范围。为了方便起见,我们进一步假设输入不包括整个IP地址空间:即0.0.0.0/0。(这可以通过一个单独的特殊情况来解决,但没有多大意义。

我需要能够输出不在给定IP地址范围列表中的所有IP地址范围

我可以使用某种算法来完成这类任务,并将其转换为工作代码

  • 基本上,我将使用Salesforce Apex代码,因此,如果给定的示例可行,任何类似JAVA的语言都可以

首先,我假设您的意思是您获得一个或多个不相交的CIDR范围作为输入,并且需要生成所有CIDR范围的列表,其中不包括任何作为输入的CIDR范围。为了方便起见,我们进一步假设输入不包括整个IP地址空间:即
0.0.0.0/0
。(这可以通过一个单独的特殊情况来解决,但没有多大意义。)

我以前也写过类似的代码,虽然我不能随意分享代码,但我可以描述方法。它本质上是一个二进制搜索算法,在这个算法中,你重复地将整个地址空间平分,直到你分离出你感兴趣的一个范围

把IP地址空间想象成一棵二叉树:根上是完整的IPv4地址空间
0.0.0/0
。它的子级分别代表地址空间的一半:
0.0.0/1
128.0.0/1。
这些子级又可以细分,分别创建子级
0.0.0.0/2
/
64.0.0/2
128.0.0.0/2
/
192.0.0.0/2,
。一直这样下去,你会得到
2**32
叶子,每个叶子代表一个
/32
(即一个地址)

现在,将此树看作是从输入列表中排除的地址空间的一部分。因此,您的任务是遍历这棵树,从树中的输入列表中找到每个范围,并删除输入中树的所有部分,留下地址空间的其余部分

幸运的是,您实际上不需要创建所有的
2**32
叶子。如果没有为CIDR
N
创建子节点,则可以假定CIDR
N+1
及以上位置的每个节点都包含所有节点(您需要一个标志来记住,它已经被细分了,即不再是叶,原因见下文)

因此,首先,整个地址空间都存在于树中,但都可以由单个叶节点表示。调用树
excluded,
并用单个节点
0.0.0/0对其进行初始化。

现在,考虑第一个输入范围——我们将调用这个代码>试用< /代码>(我将使用<代码> 1427.34.0/ 24 作为初始<代码>试用< /COD>值,只为演示提供一个具体的值)。任务是从

excluded
中删除
trial
,留下剩余的地址空间

current
节点指针设置为
excluded
根节点开始

开始:

试验
CIDR与
当前
进行比较。如果是相同的,就完成了(但如果输入范围不相交,并且从输入中排除了
0.0.0.0/0
,则永远不会发生这种情况)

否则,如果
current
是叶节点(尚未细分,这意味着它表示此CIDR级别及以下的整个地址空间),则设置其sub-divided标志,并为其创建两个子节点:指向其地址空间前半部分的
left
指针和指向后半部分的
right
指针。适当地标记每个节点(对于根节点的子节点,将是
0.0.0.0/1
128.0.0.0/1

确定
试验
CIDR是在
当前
的左侧还是右侧。对于我们的初始
试用值
值,它位于左侧。现在,如果那一侧的指针已经是空的,那么您就完成了(尽管如果您的输入范围不相交,“不可能发生”)

如果
trial
CIDR与该侧节点中的CIDR完全相同,则只需释放该节点(以及它可能具有的任何子节点,如果只有不相交的输入,则该子节点也应为无),将指针设置为该侧
NULL
,即可完成操作。你刚刚把那片叶子从树上剪下来,把整个范围都排除了

如果试验值与该侧节点中的CIDR不完全相等,则将
current
设置到该侧并重新开始(即跳到上面的start标签)

因此,初始输入范围为
14.27.34.0/24
,首先将
0.0.0/0
分为
0.0.0/1
128.0.0.0/1
。然后从左侧下拉并将
0.0.0/1
拆分为
0.0.0/2
64.0.0/2。
然后再次从左侧下拉以创建
0.0.0/3
32.0.0.0/3.
等等,直到23次拆分之后,然后将
14.27.34.0/23
拆分为
14.27.34.0/24
14.27.35.0/24。
然后删除左侧
14.27.34.0/24
子节点,并将其指针设置为
NULL
,保留另一个节点

这将为您留下一个包含24个叶节点的稀疏树(在您删除目标节点之后)。其余叶节点用*标记:

                             (ROOT)
                           0.0.0.0/0
                            /     \
                      0.0.0.0/1  128.0.0.0/1*
                        /    \
                 0.0.0.0/2  64.0.0.0/2*
                  /     \
            0.0.0.0/3  32.0.0.0.0/3*
              /    \
       0.0.0.0/4  16.0.0.0/4*
           /  \
  *0.0.0.0/5  8.0.0.0/5
               /    \
       *8.0.0.0/6  12.0.0.0/6
                      /    \
             *12.0.0.0/7  14.0.0.0/7
                             /    \
                     14.0.0.0/8  15.0.0.0/8*
                        /    \
                     ...
                /       \
     *14.27.32.0/23  14.27.34.0/23
                      /       \
                  (null)     14.27.35.0/24*
          (14.27.34.0/24)
对于每个剩余的输入范围,您将再次运行树,在必要时将叶节点一分为二,通常会产生更多的叶,但始终会删除部分地址空间

最后,您只需按照方便的顺序遍历生成的树,收集剩余叶子的苹果酒。请注意,在此阶段中,您必须排除以前细分的项目。例如,在上面的树中,如果您下一次处理输入范围<代码> 1427.35.0/ 24 ,您将离开<代码> 1427.34.0/ 23 < /代码>,没有CHI。
public class NetworkRange {

    private long startAddress;
    private long endAddress;

    public NetworkRange(String start, String end) {
        startAddress = addressRepresentationToAddress(start);
        endAddress = addressRepresentationToAddress(end);
    }

    public NetworkRange(long start, long end) {
        startAddress = start;
        endAddress   = end;
    }

    public String getStartAddress() {
        return addressToAddressRepresentation(startAddress);
    }

    public String getEndAddress() {
        return addressToAddressRepresentation(endAddress);
    }

    static String addressToAddressRepresentation(long address) {
        String result = String.valueOf(address % 256);

        for (int i = 1; i < 4; i++) {
            address = address / 256;
            result = String.valueOf(address % 256) + "." + result;
        }

        return result;
    }

    static long addressRepresentationToAddress(String addressRep) {
        long result = 0L;
        String[] tokens = addressRep.split("\\.");

        for (int i = 0; i < 4; i++) {

            result += Math.pow(256, i) * Long.parseLong(tokens[3-i]);
        }

        return result;
    }

    public List<NetworkRange> splitByExcludedRange(NetworkRange excludedRange) {
        if (this.startAddress == excludedRange.startAddress && this.endAddress == excludedRange.endAddress)
            return Arrays.asList();

        if (this.startAddress == excludedRange.startAddress)
            return Arrays.asList(new NetworkRange(excludedRange.endAddress+1, this.endAddress));

        if (this.endAddress == excludedRange.endAddress)
            return Arrays.asList(new NetworkRange(this.startAddress, excludedRange.startAddress-1));

        return Arrays.asList(new NetworkRange(this.startAddress, excludedRange.startAddress-1),
                             new NetworkRange(excludedRange.endAddress+1, this.endAddress));
    }

    public boolean includes(NetworkRange excludedRange) {
        return this.startAddress <= excludedRange.startAddress && this.endAddress >= excludedRange.endAddress;
    }

    public String toString() {
        return "[" + getStartAddress() + "-" + getEndAddress() + "]";
    }
}
public class RangeProducer {

    private NetworkRange global;

    public RangeProducer(NetworkRange global) {
     this.global = global;
    }

    public List<NetworkRange> computeEffectiveRanges(List<NetworkRange> excludedRanges) {
        List<NetworkRange> effectiveRanges = new ArrayList<>();
        effectiveRanges.add(global);
        List<NetworkRange> effectiveRangesSplitted = new ArrayList<>();

        for (NetworkRange excludedRange : excludedRanges) {
            for (NetworkRange effectiveRange : effectiveRanges) {
                if (effectiveRange.includes(excludedRange)) {
                    effectiveRangesSplitted.addAll(effectiveRange.splitByExcludedRange(excludedRange));
                } else {
                    effectiveRangesSplitted.add(effectiveRange);
                }
            }

            effectiveRanges = effectiveRangesSplitted;
            effectiveRangesSplitted = new ArrayList<>();
        }
        return effectiveRanges;
    }
}
public static void main(String[] args) {
        NetworkRange global = new NetworkRange("10.0.0.0", "10.255.255.255");

        NetworkRange ex1 = new NetworkRange("10.0.0.0", "10.0.1.255");
        NetworkRange ex2 = new NetworkRange("10.1.0.0", "10.1.1.255");
        NetworkRange ex3 = new NetworkRange("10.6.1.0", "10.6.2.255");
        List<NetworkRange> excluded = Arrays.asList(ex1, ex2, ex3);

        RangeProducer producer = new RangeProducer(global);

        for (NetworkRange effective : producer.computeEffectiveRanges(excluded)) {
            System.out.println(effective);
        }
    }
[10.0.2.0-10.0.255.255]
[10.1.2.0-10.6.0.255]
[10.6.3.0-10.255.255.255]