【发布时间】:2014-08-16 12:02:52
【问题描述】:
我正在尝试一种有效的数据结构来表示 IP 范围,如下所述。我知道我想尝试的东西很容易实现,但我似乎无法确定。
假设我有数百个单独的 IP 范围,格式为 1.1.1.0 - 1.1.2.255 或其他格式(但不是 CIDR 格式,如 1.1.1.0/24)。
不同的范围不是连续的,因此在一个结束和下一个开始之间可能有数百万个 IP。如果愿意,它们可以/将用整数格式表示(即,在本例中为 16843008 - 16843519)。
不会有已知的 IP 地址与其他范围重叠。
基本上,如果您好奇的话,这些范围代表 ASN 网络块。我需要制作一个工具来确定任何给定的 IP 是否适合这些范围之一——但该工具必须相当快(理想情况下小于 0.5 秒)。
现在,如果我有成百上千个这样的范围,涵盖数百万个 IP,并且想要查找给定 IP 是否在其中一个范围内(或不在),那么最快的方法是什么?内存太密集?
我能想到几个选项:
构建一个包含所有范围内的每个 IP 的 HashSet,然后针对它执行 contains(ip)。我预计那里有大约 5000 万个 IP。速度快,但似乎有点浪费,内存明智?
有一个TreeMap,它的键是每个范围的起始IP,它的值是结束IP。如果测试 IP 大于该键但小于下一个键,则遍历树并检查每个键。如果是,则调查该值(即范围的结束 IP),如果 IP 小于映射的值,则 IP 在范围内 - 如果不是,则继续没有意义,可以假设 IP 不在在任何范围内。是否可以通过树的键进行二进制搜索以更快地得出结论,而不是按顺序检查?
1234563 .211, 211.211.215", etc... 然后,如果我被要求检查 IP 123.123.124.144,我可以首先查看它的子网 (123.123.124) 是否是地图中的一个键。映射的值可能是一个自定义对象,其中包含与该特定子网关联的范围的开始和结束 IP。然后您可以使用它来检查完整的 IP 是否适合该范围。这个特殊对象将与映射中的许多条目共享,因为显然在给定范围内可能有许多子网。
那么,有什么想法/想法/意见吗?我有一种感觉,我的第二个想法可能有一条好路要走?感谢您提供信息...很高兴听到您的想法!
【问题讨论】:
-
我越想这个问题,我就意识到这个问题对我来说很容易解决。只需保留一个庞大的 HashMap,其中的键是每个范围中每个可能的子网。它的最大尺寸为 1764705,但对我来说,它只会是其中的 5%——所以它不是太大。我忘记了子网中的每个 IP 都可以被同等对待,因为 ASN 的分解不能小于子网级别。
标签: search data-structures ip range cidr