解析CIDR表示的IP段表示的范围

需求:给定一个ip:172.28.68.0和一个CIDR格式的ip配置项ipConfig="172.28.64.0/22,172.28.72.11;172.16.0.0/12,172.28.80.27",判断该IP是在哪个cidr表示的地址段,并获取cidr格式后面的一个ip地址。 
    首先,要对cidr表示法要有所了解。 
    例如:172.28.64.0/22表示前22位不变,用1表示,后10位表示网络主机范围,相应的掩码表示为:11111111 11111111 11111100 00000000即该CIDR的掩码为:255.255.252.0 

    然后根据公式计算地址范围: 
   


  •     
  • 网络地址 = IP address & Mask    
  • 网络广播地址 = Network address + Mask反码    
  • 地址范围 = { 网络地址, 网络地址 + Mask反码}   


    例如: 
        IP address = 200.6.12.55,Mask = 255.255.248.0 
        网络地址 = 200.6.12.55 &  255.255.248.0 = 200.6.8.0 
        地址范围 = {200.6.8.0,200.6.15.255} 
    确定范围后如何快速判断一个IP是否在该CIDR表示的范围内?这里用的技巧是把ip转换为256进制的数,再看该IP是否在范围内。 

 

Java代码  

  1. /** 
  2.  *  
  3.  */  
  4. package com.zrf.ip;  
  5.   
  6. import java.util.HashMap;  
  7. import java.util.Map;  
  8.   
  9. /** 
  10.  * @author zhongrunfu 
  11.  * 日期:2014-10-28 
  12.  * 描述:根据某个IP,查找相应的CIDR IP地块,以及目标主机地址 
  13.  *  
  14.  */  
  15. public class IpRouter {  
  16.     /**最大IP的256进制LONG值的KEY*/  
  17.     public static final String CIDR_MAX_IP = "CIDR_MAX_IP";  
  18.     /**最小IP的256进制LONG值的KEY*/  
  19.     public static final String CIDR_MIN_IP = "CIDR_MIN_IP";  
  20.     /* 
  21.      * cidrIp与目标IP映射表 
  22.      * 例如:configIp = 172.38.64.0/22,172.28.72.11 
  23.      * key=172.38.64.0/22 
  24.      * value=172.28.72.11 
  25.      */  
  26.     private Map cidrIpToTargetIp;  
  27.     /* 
  28.      * cidrIp表示的范围 
  29.      * 用256进制值表示最大最小值 
  30.      * 其中包括非法IP(主机ID全为0或1的IP) 
  31.      * 例如:cidrIp = 172.38.64.0/22 
  32.      * value = Map,MAP 
  33.      */  
  34.     private Map cidrIpBlock;  
  35.     /* 
  36.      * CIDR IP 数组 
  37.      * 例如:[172.28.64.0/22,172.16.0.0/12] 
  38.      */  
  39.     private String[] cidrIps;  
  40.     /** 
  41.      * 构造方法 
  42.      *  
  43.      * @param bindIpConfig 配置项 
  44.      * 例如:172.28.64.0/22,172.28.72.11;172.16.0.0/12,172.28.80.27 
  45.      */  
  46.     public IpRouter(String bindIpConfig){  
  47.         this.init(bindIpConfig);//初始化  
  48.     }  
  49.     /** 
  50.      * 获取目标IP 
  51.      * 如果CIDR格式的IP段有重复,则返回首个地址 
  52.      * @param ip 给定的IP地址 
  53.      * @return 
  54.      */  
  55.     public String rout(String ip){  
  56.         if(ip==null||"".equals(ip.trim())){  
  57.             return null;  
  58.         }  
  59.         long ipValue = this.ipToNumeric(ip);//IP转换为256进制值  
  60.         String cidrIp = "";  
  61.         for(int i=0,len=this.cidrIps.length;i
  62.             cidrIp = this.cidrIps[i];  
  63.             if(this.isInBlock(ipValue, (Map)this.cidrIpBlock.get(cidrIp))){  
  64.                 return (String)this.cidrIpToTargetIp.get(cidrIp);  
  65.             }  
  66.         }  
  67.         return null;  
  68.     }  
  69.     /* 
  70.      * 判断是否在给定的范围内 
  71.      *   
  72.      * @param ipValue 判断的IP 
  73.      * @param blockMap IP值范围 
  74.      * @return 如果是返回true,否则返回false 
  75.      */  
  76.     private boolean isInBlock(long ipValue,Map blockMap){  
  77.         Long maxIpValue = (Long)blockMap.get(IpRouter.CIDR_MAX_IP);  
  78.         Long minIpValue = (Long)blockMap.get(IpRouter.CIDR_MIN_IP);  
  79.         return (ipValue>=minIpValue.longValue())&&(ipValue<=maxIpValue.longValue());  
  80.     }  
  81.     /* 
  82.      * 初始化  
  83.      * @param bindIpConfig 格式172.28.64.0/22,172.28.72.11;172.16.0.0/12,172.28.80.27 
  84.      */  
  85.     private void init(String bindIpConfig){  
  86.         this.print("初始化开始--------->");  
  87.         long time = System.currentTimeMillis();  
  88.         if(bindIpConfig==null||"".equals(bindIpConfig.trim())){  
  89.             throw new RuntimeException("参数不能为空");  
  90.         }  
  91.         this.print("");  
  92.         String[] bindIps = bindIpConfig.split(";");  
  93.         if(bindIps==null||bindIps.length==0){  
  94.             throw new RuntimeException("参数格式不正确,必须像以下格式x.x.x.x/n,a.a.a.a;x.x.x.x/n;b.b.b.b");  
  95.         }  
  96.         int len = bindIps.length;  
  97.         this.cidrIps = new String[len];//----  
  98.         this.cidrIpBlock = new HashMap();//----  
  99.         this.cidrIpToTargetIp = new HashMap();//----  
  100.         String[] cidrIpTargetIp = null;  
  101.         for(int i=0;i
  102.             this.print("02--开始按,号分割["+bindIps[i]+"]");  
  103.             cidrIpTargetIp = bindIps[i].split(",");//分割CIDR与目标IP地址  
  104.             if(cidrIpTargetIp==null||cidrIpTargetIp.length!=2){  
  105.                 throw new RuntimeException("参数格式不正确,CIDR地址与目标IP地址需要逗号分格,例如:x.x.x.x/n,a.a.a.a");  
  106.             }  
  107.             cidrIps[i] = cidrIpTargetIp[0];//CIDR地址  
  108.             this.cidrIpToTargetIp.put(cidrIpTargetIp[0], cidrIpTargetIp[1]);//-->map  
  109.             this.initCidrIpBlock(cidrIpTargetIp[0]);  
  110.         }  
  111.         this.print("初始化完成---->共花费时间(毫秒):"+(System.currentTimeMillis()-time));  
  112.     }  
  113.     /* 
  114.      * 初始化CIDR IP范围 
  115.      * @param cidrIp 例如:x.x.x.x/n 
  116.      */  
  117.     private void initCidrIpBlock(String cidrIp){  
  118.         this.print("初始化CIDR IP范围,CIDR IP=["+cidrIp+"]");  
  119.         if(cidrIp==null||"".equals(cidrIp.trim())){  
  120.             throw new RuntimeException("["+cidrIp+"]参数格式不正确,CIDR地址部分为空");  
  121.         }  
  122.         String[] ipIds = cidrIp.split("\\/");  
  123.         if(ipIds==null||ipIds.length!=2){  
  124.             throw new RuntimeException("["+cidrIp+"]参数格式不正确,CIDR地址格式不正确,正确格式为x.x.x.x/n");  
  125.         }  
  126.         int num = Integer.parseInt(ipIds[1]);  
  127.         if(num>32||num<4){  
  128.             throw new RuntimeException("["+cidrIp+"]参数格式不正确,CIDR地址格式不正确,网络ID值必须在(4,32)范围内");  
  129.         }  
  130.         //TODO  
  131.         String networkId = this.getNetworkId(cidrIp);  
  132.         String maxIpAddres = this.getMaxIpAddres(networkId, this.getMaskRevert(num));  
  133.         Map map = new HashMap();  
  134.         map.put(IpRouter.CIDR_MAX_IP, Long.valueOf(this.ipToNumeric(maxIpAddres)));  
  135.         map.put(IpRouter.CIDR_MIN_IP, Long.valueOf(this.ipToNumeric(networkId)));  
  136.         this.cidrIpBlock.put(cidrIp, map);//cidr ip范围  
  137.         this.print("["+cidrIp+"]IP 256进制值范围为["+map.get(IpRouter.CIDR_MIN_IP)+","+map.get(IpRouter.CIDR_MAX_IP)+"]");  
  138.         this.print("["+cidrIp+"]IP 范围为["+networkId+","+maxIpAddres+"]");  
  139.     }  
  140.     /* 
  141.      * 获取网络ID,即也是CIDR表示的最小IP 
  142.      * @param ipCidr CIDR法表示的IP,例如:172.16.0.0/12 
  143.      * @return 网络ID,即也是CIDR表示的最小IP 
  144.      */  
  145.     private String getNetworkId(String ipCidr){  
  146.         String[] ipMaskLen = ipCidr.split("\\/");  
  147.         String mask = this.getMask(Integer.parseInt(ipMaskLen[1]));  
  148.         String[] ips = ipMaskLen[0].split("\\.");  
  149.         String[] masks = mask.split("\\.");  
  150.         StringBuffer sb = new StringBuffer();  
  151.         for(int i=0;i<4;i++){  
  152.             sb.append(Integer.parseInt(ips[i])&Integer.parseInt(masks[i]));  
  153.             if(i!=3){  
  154.                 sb.append(".");  
  155.             }  
  156.         }  
  157.         return sb.toString();  
  158.     }  
  159.     /* 
  160.      * 获取掩码 
  161.      * @param maskLength 网络ID位数 
  162.      * @return 
  163.      */  
  164.     private String getMask(int maskLength){  
  165.         int binaryMask = 0xFFFFFFFF << (32 - maskLength);  
  166.         StringBuffer sb = new StringBuffer();  
  167.         for(int shift=24;shift>0;shift-=8){  
  168.             sb.append(Integer.toString((binaryMask>>>shift)&0xFF));  
  169.             sb.append(".");  
  170.         }  
  171.         sb.append(Integer.toString(binaryMask&0xFF));  
  172.         return sb.toString();  
  173.     }  
  174.     /* 
  175.      * 获取IP最大值 
  176.      * @param netId 网络ID 
  177.      * @param maskReverse 掩码反码 
  178.      * @return 
  179.      */  
  180.     private String getMaxIpAddres(String netId,String maskReverse){  
  181.         String[] netIdArray = netId.split("\\.");  
  182.         String[] maskRevertArray = maskReverse.split("\\.");  
  183.         StringBuffer sb = new StringBuffer();  
  184.         for(int i=0,len=netIdArray.length;i
  185.             sb.append(Integer.parseInt(netIdArray[i])+Integer.parseInt(maskRevertArray[i]));  
  186.             if(i!=len-1){  
  187.                 sb.append(".");  
  188.             }  
  189.         }  
  190.         return sb.toString();  
  191.     }  
  192.     /* 
  193.      * 获取掩码整型数组  
  194.      * @param maskLength 网络ID位数 
  195.      * @return 
  196.      */  
  197.     private int[] getmaskArray(int maskLength){  
  198.         int binaryMask = 0xFFFFFFFF << (32 - maskLength);  
  199.         int[] mask = new int[4];  
  200.         for(int shift=24,k=0;shift>0;shift-=8){  
  201.             mask[k] = (binaryMask>>>shift)& 0xFF;  
  202.             k++;  
  203.         }  
  204.         mask[3] = binaryMask & 0xFF;  
  205.         return mask;  
  206.     }  
  207.     /* 
  208.      * 获取掩码的反码  
  209.      * @param maskLength 网络ID位数 
  210.      * @return 
  211.      */  
  212.     private String getMaskRevert(int maskLength){  
  213.         int binaryMask = 0xFFFFFFFF << (32 - maskLength);  
  214.         binaryMask = binaryMask ^ 0xFFFFFFFF;  
  215.         StringBuffer sb = new StringBuffer(15);  
  216.         for(int shift=24;shift>0;shift-=8){  
  217.             sb.append(Integer.toString((binaryMask>>>shift)&0xFF));  
  218.             sb.append(".");  
  219.         }  
  220.         sb.append(Integer.toString(binaryMask&0xFF));  
  221.         return sb.toString();  
  222.     }  
  223.     /* 
  224.      * IP地址转换为一个256进制的long整数  
  225.      * @param ip 
  226.      * @return 
  227.      */  
  228.     private long ipToNumeric(String ip){  
  229.         String[] ips = ip.split("\\.");  
  230.         Long[] ipLong = new Long[4];  
  231.         for(int i=0,len=ips.length;i
  232.             ipLong[i] = Long.parseLong(ips[i]);  
  233.         }  
  234.         long result = ipLong[3] & 0xFF;  
  235.         result |= ((ipLong[2]<<8)) & 0xFF00;  
  236.         result |= ((ipLong[1]<<16)) & 0xFF0000;  
  237.         result |= ((ipLong[0]<<24)) & 0xFF000000;  
  238.         return result;  
  239.     }  
  240.     /* 
  241.      * 十进制转二进制 
  242.      * @param n 
  243.      * @return 
  244.      */  
  245.     private String toBinary(int n){  
  246.         return Integer.toBinaryString(n);  
  247.     }  
  248.     /* 
  249.      * 二进制转十进制 
  250.      * @param bit 
  251.      * @return 
  252.      */  
  253.     private int binaryToTen(String bit){  
  254.         return Integer.valueOf(bit,2);  
  255.     }  
  256.       
  257.     private void print(Object obj){  
  258.         System.out.println(obj);  
  259.     }  
  260.     /** 
  261.      * @param args 
  262.      */  
  263.     public static void main(String[] args) {  
  264.         // TODO Auto-generated method stub  
  265.         String ipConfig = "172.28.64.0/22,172.28.72.11;172.16.0.0/12,172.28.80.27";  
  266.         String ip = "172.28.68.0";  
  267.         IpRouter router = new IpRouter(ipConfig);  
  268.         long time = System.currentTimeMillis();  
  269.         router.print("请求地址:"+ip);  
  270.         router.print("目标地址:"+router.rout(ip));  
  271.         router.print("共花费时间(毫秒):"+(System.currentTimeMillis()-time));  
  272.           
  273.         router.print("-----------------------------");  
  274.         String ipCidr = "172.28.64.0/22";  
  275.         int num = 22;  
  276.         router.print("CIDR IP:["+ipCidr+"]");  
  277.           
  278.         String mask = router.getMask(num);  
  279.         router.print("掩码:["+mask+"]");  
  280.           
  281.         int[] getmaskArray = router.getmaskArray(num);  
  282.         router.print("掩码整型数组:["+getmaskArray+"]");  
  283.           
  284.         String networkId = router.getNetworkId(ipCidr);  
  285.         router.print("网络ID(最小IP):["+networkId+"]");  
  286.           
  287.         String maskRevert = router.getMaskRevert(num);  
  288.         router.print("掩码:["+mask+"]"+"的反码:["+maskRevert+"]");  
  289.           
  290.         String maxIpAddres = router.getMaxIpAddres(networkId, maskRevert);  
  291.         router.print("最大IP地址:["+maxIpAddres+"]");  
  292.           
  293.         long minIpValue = router.ipToNumeric(networkId);  
  294.         long maxIpValue = router.ipToNumeric(maxIpAddres);  
  295.         router.print("["+ipCidr+"]IP 256进制值范围为["+minIpValue+","+maxIpValue+"]");  
  296.     }  

 

转自:http://zhongrf.iteye.com/blog/2153853。谢谢!

你可能感兴趣的:(java编码及问题)