`
sam_hg
  • 浏览: 4177 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Apnic IP地址acl算法

阅读更多
Apnic 什么玩意? look here http://baike.baidu.com/view/96315.html?fromTaglist

可以通过连接http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest获取到亚洲所有国家的ip地址信息(包括Ipv4和Ipv6,这里只讨论ipv4。类似Apnic这样的机构全球有5个,其他4个可以Google)。

以下是ip地址信息的一个片段

    apnic|CN|ipv4|222.249.160.0|4096|20040721|allocated
    apnic|CN|ipv4|222.249.176.0|4096|20050511|allocated
    apnic|CN|ipv4|222.249.192.0|16384|20050511|allocated
    apnic|TW|ipv4|222.250.0.0|65536|20040525|allocated
    apnic|TW|ipv4|222.251.0.0|32768|20040525|allocated
    apnic|KR|ipv4|222.251.128.0|32768|20051215|allocated
    apnic|VN|ipv4|222.252.0.0|262144|20040518|allocated


我们只关心每行信息中第2、4、5列的信息。
例如:第一行的,CN,222.249.160.0,4096三列的值,分别表示国家,开始ip,ip个数。这一列可以变成acl的格式 CN 222.249.160.0/20,这样就方便我们把这样包含了4096个ip地址的记录存放到二叉树中进行一些,查询,更新的操作(我怀疑qq纯真库就是用这种方法进行查询的)。

以下是一段实现这个算法的一段代码,包括ip地址acl的insert和merge操作(包含了查询)


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


public class AclTree {
	private static final Integer MASK = 0x00000001;
	private Node root;
	private List<String> codelist;
	private List<String> results;
	
	public AclTree(){
		root = null;
		codelist = new ArrayList<String>();
		results  = new ArrayList<String>();
	}
	
	public String getStrIpBy32Int(Long k){
		String ip="";
		Long p1 = ( (k&0xff000000)>>24 );
		Long p2 =( (k&0x00ff0000)>>16 );
		Long p3 =  (k&0x0000ff00)>>8;
		Long p4 = ( k&0x000000ff );
		ip=p1.toString() +"."+ p2.toString() +"."+p3.toString()+"."+p4.toString();
		
		return ip;
	}
	
	public Long get32IntIpByIp(String ip){
		Long ipInt = new Long(0);
		String[] ps = ip.split("\\.");
		if(4 != ps.length){
			return ipInt;
		}
		Long p1 = new Long( ps[0] );
		Long p2 = new Long( ps[1] );
		Long p3 = new Long( ps[2] );
		Long p4 = new Long( ps[3] );
		ipInt = p1*256*256*256 + p2*256*256 + p3*256 + p4;
		return ipInt;
	}
	
	private int getIndex(String obj){

		int index = this.codelist.indexOf(obj);
		if(0 > index){
			index = this.codelist.size();
			this.codelist.add(obj);
		}
		if("HuaShu"==obj){
			System.out.println(index);
		}
		return index;
	}
	
	private Node insertNewNode(byte k, short v, Node n){
		
		if(0 == k){//left child
			
			if(null == n.left){
				n.left = new Node();
			}
			if(null != n.codeIndex){ //split father to two leaf nodes
				n.right = new Node();
				n.right.codeIndex = n.codeIndex;
				n.left.codeIndex = n.codeIndex;
				n.codeIndex = null;
				
			}
			return n.left;
		}else if( 1== k){//right child
			
			if(null == n.right){
				n.right = new Node();
			}
			if( null != n.codeIndex ){//split father to two leaf nodes
				n.left = new Node();
				n.left.codeIndex = n.codeIndex;
				n.right.codeIndex = n.codeIndex;
				n.codeIndex = null;
			}
			return n.right;
		}
		
		return null;
	}
	

	
	private void merge(Node node){
		if(null == node){
			return;
		}
		if( null != node.codeIndex ){ //leaf node
//			if(246 == node.codeIndex){
//				System.out.println("");
//			}
			return;
		}
		if( null != node.left ){
			merge( node.left );
		}
		if( null != node.right){
			merge( node.right );
		}
		if( (null != node.left)&&(null != node.right) ){
			if ( (null != node.left.codeIndex)&&(null != node.right.codeIndex) ){
				int l = node.left.codeIndex.intValue();
				int r = node.right.codeIndex.intValue();
				if(l == r){
					if( null != node.left.codeIndex){//merge two children
						node.codeIndex = node.left.codeIndex;
						node.left = null;
						node.right = null;
					}
				}
			}
			

		}
	}
	
	private void collectLeaves(Node node, long route, int level){
		if(null == node){
			return;
		}
		if(null != node.codeIndex){
			long key = route<<(32-level);
			String rs = this.codelist.get(node.codeIndex)+" "+this.getStrIpBy32Int(key)+" "+level;
			this.results.add(rs);
//			System.out.println(rs);
			return;
		}
		long tmpRoute = route;
		if(this.root != node){
			tmpRoute = route<<1;
		}
		if(null != node.left){
			int x = level+1; 
			this.collectLeaves( node.left, tmpRoute, x );
		}
		if(null != node.right){
			int x = level+1;
			this.collectLeaves( node.right, tmpRoute+1, x );
		}
		
	}
	
	public void insert(String ipInt, String areaCode, Integer mask){
		if(null == this.root){
			this.root = new Node();
		}
		Node node = this.root;
		short index = (short)this.getIndex(areaCode);
		
		long x = new Long(ipInt);		
		x = x>>(32-mask);
		for(int i = mask-1; i >= 0; i--){
			byte k = (byte)( (x>>i)&MASK );
			if(null != node.codeIndex){// repeat the same index
				if(index == node.codeIndex){
					break;
				}
			}
			node = insertNewNode(k, index, node);
		}
		
		node.codeIndex = index;
	}
	
	public List< String > getAclData(){
		this.merge(this.root);
		this.collectLeaves(this.root, 0, 0);
		return this.results;
		
	}
	
	public static void main(String args[]){
		
		AclTree tmp =  new AclTree();
		Long x = tmp.get32IntIpByIp("110.152.0.0");
		Long y = tmp.get32IntIpByIp("110.152.1.0");
		tmp.insert(x.toString(), "xx", 23);
		tmp.insert(y.toString(), "aa", 25);
		System.out.println( tmp.getAclData() );

	}

}

class Node{
	Short   codeIndex = null;
	Node 	right = null;
	Node 	left = null;
}





分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics