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;
}