1.问题描述
假设有一堆网段,如下所示:
192.168.1.100-192.168.1.120,AAA,id1
192.168.1.50-192.168.1.150,BBB,id2
10.67.1.1/24,CCC,id3
10.67.1.1,DDD,id4
10.67.1.0,EEE,id5
第一列是单IP或者网段,第二列是设备hash,第三列是这个IP或者网段的唯一标志。IP与网段、网段与网段之间是可以有交叉的,比如192.16.1.100-192.168.1.120和192.168.1.50-192.168.1.150就是存在一部分交叉的。
要求,当一个日志过来过来时,需要得到它里面的IP的唯一ID,比如10.67.1.125过来,我们就知道它是属于10.67.1.1/24网段,那么就是用id3来标志它;比如10.67.1.1过来时,我们发现既可以命中10.67.1.1(id4)也可以命中10.67.1.1/24(id3),那么就提取日志里记录的hash值,比如hash是CCC,那么我们就知道它的唯一ID应该是id3。
2.解题思路
1.首先将网段拆开为多个不交叉的段,并且记录每个段对应的相关信息
2.在一个日志过来时,提取其IP在网段里进行二分查找,当查找到的相关信息唯一时,直接返回;当查找到的相关信息不唯一时,使用hash值进行比对,从而拿到命中值
2.1网段拆分为不交叉段
对于一组数据,如下所示:
s1,e1,id1
s2,e2,id2
s3,e3,id3
s和e分别代表起始数值,id为唯一标志。它们的范围如下图所示:

我们可以按数值的大小进行排序,注意,如果两个值相等的情况下,起始值排在结束值之前,排序之后如下所示:
s1,s2,s3,e1,e2,e3
分析的过程如下图所示:

在step1,得到的结果应该是:[s1,s2-1] id1
在step2,得到的结果应该是:[s2,s3-1] id1,id2
在step3,得到的结果应该是:[s3,e1] id1,id2,id3
在step4,得到的结果应该是:[e1+1,e2] id2,id3
在step5,得到的结果应该是:[e2+1,e3] id3
那么总结的处理过程如下:
从排序后的数值list里拿到两个元素n1,n2,用一个全局的S记录id值
- 如果n1是s类型,则a=n1,且将n1对应的id加入S中;如果n1是e类型,则a=n1+1,则将n1对应的id从S中移除
- 如果n2是s类型,则b=n2-1;如果n2是e类型,则b=n2
- 如果a<=b且S不为空,则对于[a,b]以及S进行输出
以此循环,直至对于list处理结束。
核心代码如下所示:
public List<OutputNode> init(List<IpRangeAsset> list){
List<GapRangeNode> gapRangeNodeList = new ArrayList<>();
for(int i=0;i<list.size();i++){
gapRangeNodeList.add(new GapRangeNode(list.get(i).getStartIpInt(),i,false));
gapRangeNodeList.add(new GapRangeNode(list.get(i).getEndIpInt(),i,true));
}
Collections.sort(gapRangeNodeList, new Comparator<GapRangeNode>() {
@Override
public int compare(GapRangeNode o1, GapRangeNode o2) {
return o1.getNumber()-o2.getNumber()<0||(o1.getNumber()==o2.getNumber()&&o2.isEnd())?-1:1;
}
});
OutputNode outputNode = new OutputNode(-1,-1);
List<OutputNode> resultList = new ArrayList<OutputNode>();
for(int i=0;i<gapRangeNodeList.size()-1;i++){
GapRangeNode n1 = gapRangeNodeList.get(i);
GapRangeNode n2 = gapRangeNodeList.get(i+1);
long n = -1;
long m = -1;
if(n1.isEnd()){
n = n1.getNumber()+1;
outputNode.removeAssetIndex(list.get(n1.getIndex()));
}else{
n = n1.getNumber();
outputNode.addAssetIndex(list.get(n1.getIndex()));
}
if(n2.isEnd()){
m = n2.getNumber();
}else{
m = n2.getNumber() - 1;
}
if(n <= m && outputNode.getAssetIndexSet().size() > 0){
OutputNode copyNode = new OutputNode(n,m);
Iterator<IpRangeAsset> iterator = outputNode.getAssetIndexSet().iterator();
while(iterator

本文介绍了一种处理大量IP地址和网段信息的高效算法,通过将网段拆分为不交叉段并采用二分查找,大幅提高了IP定位速度,减少查找耗时3个数量级。
最低0.47元/天 解锁文章
1378

被折叠的 条评论
为什么被折叠?



