需求:给定一个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代码
- /**
- *
- */
- package com.zrf.ip;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * @author zhongrunfu
- * 日期:2014-10-28
- * 描述:根据某个IP,查找相应的CIDR IP地块,以及目标主机地址
- *
- */
- public class IpRouter {
- /**最大IP的256进制LONG值的KEY*/
- public static final String CIDR_MAX_IP = "CIDR_MAX_IP";
- /**最小IP的256进制LONG值的KEY*/
- public static final String CIDR_MIN_IP = "CIDR_MIN_IP";
- /*
- * cidrIp与目标IP映射表
- * 例如:configIp = 172.38.64.0/22,172.28.72.11
- * key=172.38.64.0/22
- * value=172.28.72.11
- */
- private Map cidrIpToTargetIp;
- /*
- * cidrIp表示的范围
- * 用256进制值表示最大最小值
- * 其中包括非法IP(主机ID全为0或1的IP)
- * 例如:cidrIp = 172.38.64.0/22
- * value = Map<MAX_VALUE,LONG>,MAP<MIN_VALUE,LONG>
- */
- private Map cidrIpBlock;
- /*
- * CIDR IP 数组
- * 例如:[172.28.64.0/22,172.16.0.0/12]
- */
- private String[] cidrIps;
- /**
- * 构造方法
- *
- * @param bindIpConfig 配置项
- * 例如:172.28.64.0/22,172.28.72.11;172.16.0.0/12,172.28.80.27
- */
- public IpRouter(String bindIpConfig){
- this.init(bindIpConfig);//初始化
- }
- /**
- * 获取目标IP
- * 如果CIDR格式的IP段有重复,则返回首个地址
- * @param ip 给定的IP地址
- * @return
- */
- public String rout(String ip){
- if(ip==null||"".equals(ip.trim())){
- return null;
- }
- long ipValue = this.ipToNumeric(ip);//IP转换为256进制值
- String cidrIp = "";
- for(int i=0,len=this.cidrIps.length;i<len;i++){
- cidrIp = this.cidrIps[i];
- if(this.isInBlock(ipValue, (Map)this.cidrIpBlock.get(cidrIp))){
- return (String)this.cidrIpToTargetIp.get(cidrIp);
- }
- }
- return null;
- }
- /*
- * 判断是否在给定的范围内
- *
- * @param ipValue 判断的IP
- * @param blockMap IP值范围
- * @return 如果是返回true,否则返回false
- */
- private boolean isInBlock(long ipValue,Map blockMap){
- Long maxIpValue = (Long)blockMap.get(IpRouter.CIDR_MAX_IP);
- Long minIpValue = (Long)blockMap.get(IpRouter.CIDR_MIN_IP);
- return (ipValue>=minIpValue.longValue())&&(ipValue<=maxIpValue.longValue());
- }
- /*
- * 初始化
- * @param bindIpConfig 格式172.28.64.0/22,172.28.72.11;172.16.0.0/12,172.28.80.27
- */
- private void init(String bindIpConfig){
- this.print("初始化开始--------->");
- long time = System.currentTimeMillis();
- if(bindIpConfig==null||"".equals(bindIpConfig.trim())){
- throw new RuntimeException("参数不能为空");
- }
- this.print("");
- String[] bindIps = bindIpConfig.split(";");
- if(bindIps==null||bindIps.length==0){
- throw new RuntimeException("参数格式不正确,必须像以下格式x.x.x.x/n,a.a.a.a;x.x.x.x/n;b.b.b.b");
- }
- int len = bindIps.length;
- this.cidrIps = new String[len];//----
- this.cidrIpBlock = new HashMap();//----
- this.cidrIpToTargetIp = new HashMap();//----
- String[] cidrIpTargetIp = null;
- for(int i=0;i<len;i++){
- this.print("02--开始按,号分割["+bindIps[i]+"]");
- cidrIpTargetIp = bindIps[i].split(",");//分割CIDR与目标IP地址
- if(cidrIpTargetIp==null||cidrIpTargetIp.length!=2){
- throw new RuntimeException("参数格式不正确,CIDR地址与目标IP地址需要逗号分格,例如:x.x.x.x/n,a.a.a.a");
- }
- cidrIps[i] = cidrIpTargetIp[0];//CIDR地址
- this.cidrIpToTargetIp.put(cidrIpTargetIp[0], cidrIpTargetIp[1]);//-->map<cidr,targetIp>
- this.initCidrIpBlock(cidrIpTargetIp[0]);
- }
- this.print("初始化完成---->共花费时间(毫秒):"+(System.currentTimeMillis()-time));
- }
- /*
- * 初始化CIDR IP范围
- * @param cidrIp 例如:x.x.x.x/n
- */
- private void initCidrIpBlock(String cidrIp){
- this.print("初始化CIDR IP范围,CIDR IP=["+cidrIp+"]");
- if(cidrIp==null||"".equals(cidrIp.trim())){
- throw new RuntimeException("["+cidrIp+"]参数格式不正确,CIDR地址部分为空");
- }
- String[] ipIds = cidrIp.split("\\/");
- if(ipIds==null||ipIds.length!=2){
- throw new RuntimeException("["+cidrIp+"]参数格式不正确,CIDR地址格式不正确,正确格式为x.x.x.x/n");
- }
- int num = Integer.parseInt(ipIds[1]);
- if(num>32||num<4){
- throw new RuntimeException("["+cidrIp+"]参数格式不正确,CIDR地址格式不正确,网络ID值必须在(4,32)范围内");
- }
- //TODO
- String networkId = this.getNetworkId(cidrIp);
- String maxIpAddres = this.getMaxIpAddres(networkId, this.getMaskRevert(num));
- Map map = new HashMap();
- map.put(IpRouter.CIDR_MAX_IP, Long.valueOf(this.ipToNumeric(maxIpAddres)));
- map.put(IpRouter.CIDR_MIN_IP, Long.valueOf(this.ipToNumeric(networkId)));
- this.cidrIpBlock.put(cidrIp, map);//cidr ip范围
- this.print("["+cidrIp+"]IP 256进制值范围为["+map.get(IpRouter.CIDR_MIN_IP)+","+map.get(IpRouter.CIDR_MAX_IP)+"]");
- this.print("["+cidrIp+"]IP 范围为["+networkId+","+maxIpAddres+"]");
- }
- /*
- * 获取网络ID,即也是CIDR表示的最小IP
- * @param ipCidr CIDR法表示的IP,例如:172.16.0.0/12
- * @return 网络ID,即也是CIDR表示的最小IP
- */
- private String getNetworkId(String ipCidr){
- String[] ipMaskLen = ipCidr.split("\\/");
- String mask = this.getMask(Integer.parseInt(ipMaskLen[1]));
- String[] ips = ipMaskLen[0].split("\\.");
- String[] masks = mask.split("\\.");
- StringBuffer sb = new StringBuffer();
- for(int i=0;i<4;i++){
- sb.append(Integer.parseInt(ips[i])&Integer.parseInt(masks[i]));
- if(i!=3){
- sb.append(".");
- }
- }
- return sb.toString();
- }
- /*
- * 获取掩码
- * @param maskLength 网络ID位数
- * @return
- */
- private String getMask(int maskLength){
- int binaryMask = 0xFFFFFFFF << (32 - maskLength);
- StringBuffer sb = new StringBuffer();
- for(int shift=24;shift>0;shift-=8){
- sb.append(Integer.toString((binaryMask>>>shift)&0xFF));
- sb.append(".");
- }
- sb.append(Integer.toString(binaryMask&0xFF));
- return sb.toString();
- }
- /*
- * 获取IP最大值
- * @param netId 网络ID
- * @param maskReverse 掩码反码
- * @return
- */
- private String getMaxIpAddres(String netId,String maskReverse){
- String[] netIdArray = netId.split("\\.");
- String[] maskRevertArray = maskReverse.split("\\.");
- StringBuffer sb = new StringBuffer();
- for(int i=0,len=netIdArray.length;i<len;i++){
- sb.append(Integer.parseInt(netIdArray[i])+Integer.parseInt(maskRevertArray[i]));
- if(i!=len-1){
- sb.append(".");
- }
- }
- return sb.toString();
- }
- /*
- * 获取掩码整型数组
- * @param maskLength 网络ID位数
- * @return
- */
- private int[] getmaskArray(int maskLength){
- int binaryMask = 0xFFFFFFFF << (32 - maskLength);
- int[] mask = new int[4];
- for(int shift=24,k=0;shift>0;shift-=8){
- mask[k] = (binaryMask>>>shift)& 0xFF;
- k++;
- }
- mask[3] = binaryMask & 0xFF;
- return mask;
- }
- /*
- * 获取掩码的反码
- * @param maskLength 网络ID位数
- * @return
- */
- private String getMaskRevert(int maskLength){
- int binaryMask = 0xFFFFFFFF << (32 - maskLength);
- binaryMask = binaryMask ^ 0xFFFFFFFF;
- StringBuffer sb = new StringBuffer(15);
- for(int shift=24;shift>0;shift-=8){
- sb.append(Integer.toString((binaryMask>>>shift)&0xFF));
- sb.append(".");
- }
- sb.append(Integer.toString(binaryMask&0xFF));
- return sb.toString();
- }
- /*
- * IP地址转换为一个256进制的long整数
- * @param ip
- * @return
- */
- private long ipToNumeric(String ip){
- String[] ips = ip.split("\\.");
- Long[] ipLong = new Long[4];
- for(int i=0,len=ips.length;i<len;i++){
- ipLong[i] = Long.parseLong(ips[i]);
- }
- long result = ipLong[3] & 0xFF;
- result |= ((ipLong[2]<<8)) & 0xFF00;
- result |= ((ipLong[1]<<16)) & 0xFF0000;
- result |= ((ipLong[0]<<24)) & 0xFF000000;
- return result;
- }
- /*
- * 十进制转二进制
- * @param n
- * @return
- */
- private String toBinary(int n){
- return Integer.toBinaryString(n);
- }
- /*
- * 二进制转十进制
- * @param bit
- * @return
- */
- private int binaryToTen(String bit){
- return Integer.valueOf(bit,2);
- }
- private void print(Object obj){
- System.out.println(obj);
- }
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- String ipConfig = "172.28.64.0/22,172.28.72.11;172.16.0.0/12,172.28.80.27";
- String ip = "172.28.68.0";
- IpRouter router = new IpRouter(ipConfig);
- long time = System.currentTimeMillis();
- router.print("请求地址:"+ip);
- router.print("目标地址:"+router.rout(ip));
- router.print("共花费时间(毫秒):"+(System.currentTimeMillis()-time));
- router.print("-----------------------------");
- String ipCidr = "172.28.64.0/22";
- int num = 22;
- router.print("CIDR IP:["+ipCidr+"]");
- String mask = router.getMask(num);
- router.print("掩码:["+mask+"]");
- int[] getmaskArray = router.getmaskArray(num);
- router.print("掩码整型数组:["+getmaskArray+"]");
- String networkId = router.getNetworkId(ipCidr);
- router.print("网络ID(最小IP):["+networkId+"]");
- String maskRevert = router.getMaskRevert(num);
- router.print("掩码:["+mask+"]"+"的反码:["+maskRevert+"]");
- String maxIpAddres = router.getMaxIpAddres(networkId, maskRevert);
- router.print("最大IP地址:["+maxIpAddres+"]");
- long minIpValue = router.ipToNumeric(networkId);
- long maxIpValue = router.ipToNumeric(maxIpAddres);
- router.print("["+ipCidr+"]IP 256进制值范围为["+minIpValue+","+maxIpValue+"]");
- }
- }
转自:http://zhongrf.iteye.com/blog/2153853。谢谢!