基于下行端口地址完整性的网络拓扑发现算法JAVA实现

经过好几个月的慵懒的生活之后终于又有机会写一些代码啦,这次的领域比较陌生,竟然是网络拓扑发现方向的,那么就在此总结一些大体思路,再粘贴一下核心代码喽,至于其余的封装就不贴了,只贴一下核心算法部分啦~~~

    接收这个任务首先拿到的是一堆的数据文件,看着就烦人,要在其中提取我想要的地址转发表?搞笑死掉,神能找得到啊,于是我首先用perl脚本对数据文件进行了简要的处理并且输出到一个文件中,由于地址转发表的相关文件有两种格式(谁知道谁搞的这种东西啊,弄了还不弄成一种格式的)于是写了两套处理脚本如下:

isoFormat.pl

 

#!/usr/bin/perl -w

my $ip;
my @content;
my $sum = 0;
my %portHash;
my %portStateHash;
my %resultHash;

open RESULTCONTENT,">>result.txt";
while(<>){
    $ip = $ARGV;
    if($ip =~ /(.+)\.txt/){
        $ip = $1;
    }
    chomp;
    if(/^iso\.3\.6\.1\.2\.1\.17\.4\.3\.1\.1\.(.+)\s=\sHex-STRING:\s(.*)/){
        chomp;
        $content[$sum] = "$_";
        $sum++;
    }
    if(/^iso\.3\.6\.1\.2\.1\.17\.4\.3\.1\.2\.(.+)\s=\sINTEGER:\s(\S*)/){
        chomp $2;
        $portHash{$1} = $2;
    }
    if(/^iso\.3\.6\.1\.2\.1\.17\.4\.3\.1\.3\.(.+)\s=\sINTEGER:\s(\S*)/){
        chomp $2;
        $portStateHash{$1} = "$portHash{$1}"."-$2";
    }
}

foreach (@content){
    if(/^iso\.3\.6\.1\.2\.1\.17\.4\.3\.1\.1\.(.+)\s=\sHex-STRING:\s(.*)/){
        $resultHash{$1} = "$portStateHash{$1}"."-$2";
    }
}

foreach(keys %resultHash){
    print RESULTCONTENT"$ip"."\-$resultHash{$_}\n";
}

 

specialFormat.pl

 

#!/usr/bin/perl -w

my $ip;
my @content;
my $sum = 0;
my %portHash;
my %portStateHash;
my %resultHash;

open RESULTCONTENT,">>result.txt";
while(<>){
    $ip = $ARGV;
    if($ip =~ /(.+)\.txt/){
        $ip = $1;
    }
    chomp;
    if(/^\w+:\sdot1dTpFdbAddress\.(.+)\s\(octet string\)\s(.+)\s?\[.+\]/){
        chomp;
        $content[$sum] = "$_";
        $sum++;
    }
    if(/^\w+:\sdot1dTpFdbPort\.(.+)\s\(integer\)\s(\w+)/){
        chomp $2;
        $portHash{$1} = $2;
    }
    if(/^\w+:\sdot1dTpFdbStatus\.(.+)\s\(integer\)\s\w+\((\w+)\)/){
        chomp $2;
        $portStateHash{$1} = "$portHash{$1}"."-$2";
    }
}

foreach (@content){
    if(/^\w+:\sdot1dTpFdbAddress\.(.+)\s\(octet string\)\s(.+)\s?\[.+\]/){
        $resultHash{$1} = "$portStateHash{$1}"."-$2";
        $resultHash{$1} =~ s/\:/ /g;
    }
}

foreach(keys %resultHash){
    print RESULTCONTENT"$ip"."\-$resultHash{$_}\n";
}
处理完成后生成了统一格式的文件即:设备ip-端口号-端口状态-转发地址

之后又手动整理了设备mac与ip的对应文件格式为:设备ip - 设备mac地址

对生成好的规范格式的文件进行初始化生成完整的java对象集那么我们的任务便是处理这些对象识别之间的链接关系:核心算法代码如下:

package com.madonglin.finder.manager.imp;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.madonglin.finder.cache.SwitchCache;
import com.madonglin.finder.manager.NetDealer;
import com.madonglin.finder.vo.Link;
import com.madonglin.finder.vo.Port;
import com.madonglin.finder.vo.Switch;

public class DownPortNetDealer implements NetDealer {

 @Override
 public List<Link> workoutNetLinks(String markMac) {
  SwitchCache cache = SwitchCache.getSwitchCache();
  List<Switch> switches = cache.getSwitchs();
  LinkedList<Switch> leafSwitches = new LinkedList<Switch>();
  List<Switch> rootSwitches = new ArrayList<Switch>();
  List<Link> links = new ArrayList<Link>();
  //分析交换机的上下行接口
  for(Switch tempSwitch : switches){
   for(String key : tempSwitch.getKeys()){
    Port tempPort = tempSwitch.getPort(key);
    List<String> allMacs = tempPort.getAllMacs();
    if(allMacs != null && allMacs.contains(markMac)){
     tempSwitch.addUpPort(tempPort);
    }else{
     tempSwitch.addDownPort(tempPort);
     //判断后代节点数
     //FIXME 交换域确定影响结果
     for(String mac : tempPort.getAllMacs()){
      Switch compareSwitch = new Switch("");
      compareSwitch.setMac(mac);
      if(switches.contains(compareSwitch)){
       tempSwitch.addChild();
       //为子设备添加祖先信息
       int index = switches.indexOf(compareSwitch);
       Switch childSwitch = switches.get(index);
       childSwitch.addParents(tempSwitch, tempPort);
      }
     }
    }
   }
  }
  
  //确定叶子节点
  for(Switch temp : switches){
   if(temp != null && 0 == temp.getChildNum()){
    leafSwitches.addLast(temp);
   }
   if(0 == temp.getParentsKeys().size()){
    rootSwitches.add(temp);
   }
  }
  //判断链接关系
  while(!leafSwitches.isEmpty()){
   Switch tempSwitch = leafSwitches.removeFirst();
   if(null != tempSwitch){
    Switch fatherSwitch = null;
    for(Switch key : tempSwitch.getParentsKeys()){
     if(null == fatherSwitch){
      fatherSwitch = key;
      //FIXME 如果相同呢?
     }else if(key.getChildNum() < fatherSwitch.getChildNum()){
      fatherSwitch = key;
     }
     key.delChild();
     if(0 == key.getChildNum()){
      leafSwitches.addLast(key);
     }
    }
    if(!rootSwitches.contains(tempSwitch)){
     Link link = new Link();
     link.setSwitchSrc(fatherSwitch.getIp());
     link.setSwitchDes(tempSwitch.getIp());
     link.setPortNumSrc(tempSwitch.getParentsPort(fatherSwitch).getNum());
     link.setPortNumDes(tempSwitch.getUpPort().get(0).getNum());
     links.add(link);
    }
   }
  }
  return links;
 }

}
看个大概意思吧哈哈,经过我测试识别结果还算比较准确的

 

你可能感兴趣的:(java,算法,cache,脚本,perl)