`

解析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是否在范围内。

/**
 * 
 */
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+"]");
	}

}

分享到:
评论

相关推荐

    nginx中geo识别ip的cidr范围到国家

    在IP_cidr.txt文件中,包含了IP地址的CIDR表示形式,这些记录通常来自于公共IP数据库,如MaxMind的GeoLite库,它们提供了IP地址与国家之间的映射关系。 要使用Nginx的`geo`模块,我们需要将IP_cidr.txt中的数据导入...

    最全最新的中国全国IP段,2亿多IP

    ### 最全最新的中国全国IP段解析 #### 一、引言 随着互联网技术的迅猛发展,IP地址作为网络通信的基础,对于确保数据准确无误地传输到目标设备至关重要。了解和掌握特定区域内的IP地址范围,对于网络安全管理、...

    IDC机房IP段

    - **IP段**:指连续的一系列IP地址范围,通过CIDR(Classless Inter-Domain Routing,无类别域间路由)表示法定义。例如,“192.168.1.0/24”表示一个包含从“192.168.1.0”到“192.168.1.255”的所有IP地址的段落。...

    全国IP段.rar全国IP段.rar全国IP段.rar

    IP段通常以CIDR(无类别域间路由)的形式表示,如1.2.3.0/24,其中1.2.3.0是起始IP地址,/24表示该IP段包含256个IP地址(2的8次方)。了解全国IP段对于网络管理和网络安全具有重要意义。 1. IP地址结构:IP地址由四...

    shell实现netmask掩码和cidr掩码位转换1

    shell实现netmask掩码和cidr掩码位转换 Shell 实现 Netmask 掩码和 CIDR 掩码位转换是一种常用的网络协议 软件/插件,经常在写脚本时需要实现掩码位和掩码之间的转换。下面将详细介绍 Shell 实现 Netmask 掩码和 ...

    辽宁ip段 .txt

    下面我们将对这些IP地址段进行详细解析。 ### IP地址基础知识 在深入分析之前,我们需要先了解一些关于IP地址的基础概念: - **IPv4地址**:由四个十进制数字组成,每个数字介于0到255之间,中间用点号分隔开...

    国内IDC IP段

    本篇将针对给定的“国内IDC IP段”进行深入解析,探讨其背后的原理和技术要点。 ### 国内游戏机房IDC段扫描的意义 游戏机房IDC段扫描是指通过自动化工具或脚本对指定范围内的IP地址进行探测,以发现开放的服务端口...

    IP地址CIDR斜线记法求子网信息软件(vs2010+MFC)

    IP地址CIDR斜线记法求子网信息软件(vs2010+MFC)最近在学习计算机网络,遇到根据斜线记法来确定该IP所在子网的信息,包括:子网号、子网掩码、第一个可用IP、最后一个可用IP、广播地址、可用IP数总量。

    世界IP段分布

    每个IP地址都属于特定的IP段,IP段是由连续的IP地址组成的集合,通常以CIDR(无类别域间路由)的形式表示,例如/24代表一个拥有256个地址的网络。IP段的划分有利于网络管理和路由优化。 世界IP段的分布并不均匀,...

    重兴地区的IP段

    CIDR使用斜杠(/)后跟一个数字来表示网络前缀长度,这个数字代表了IP地址中网络部分的位数。例如,222.182.90.0/24 表示的是从222.182.90.0到222.182.90.255的地址范围。 ### 三、文件内容解析 #### 1. 地址范围...

    甘肃ip段甘肃ip段

    而IP段则是指一系列连续的IP地址,通常表示为起始IP地址和结束IP地址,或者通过CIDR(无类别域间路由)表示法来表示,如`202.100.0.0/16`表示从`202.100.0.0`到`202.100.255.255`的所有地址。 ### 甘肃省的IP段分析...

    电信常用ip段

    ### 电信常用IP段解析 #### 一、概述 在互联网世界中,IP地址作为设备在网络中的唯一标识,对于网络通信至关重要。对于大型运营商如中国电信而言,拥有的IP地址资源非常丰富,这些资源被用于满足不同场景下的需求...

    非常强悍的JS 实现IP地址分配 源码

    2. 子网掩码与CIDR:子网掩码用于定义网络部分和主机部分,而CIDR(无类别域间路由)表示法简化了IP地址和子网的表示。 二、JavaScript处理IP地址 1. 字符串解析:JavaScript可以使用内置函数将点分十进制的IP地址...

    IP地址段与子网掩码计算表

    ### IP地址段与子网掩码计算表解析 在计算机网络中,IP地址与子网掩码是两个非常重要的概念,它们共同决定了一个网络中主机的通信方式以及网络的划分方式。本文将根据给定的“IP地址段与子网掩码计算表”中的数据,...

    IP路由协议疑难解析

    6. 路由聚合:为了减少路由表的大小和路由传播的开销,路由协议支持路由聚合,将多个连续的IP地址段聚合为一个更小的地址块。 7. 路由重分布:在多协议环境中,不同路由协议之间的路由信息需要互相传递,这就涉及到...

    最新ip数据字典

    1. **IP地址的组成**:IP地址(Internet Protocol Address)是由32位二进制数组成的,通常分为四段,每段8位,用十进制表示,并用点号分隔,即IPv4格式。例如,192.168.0.1。在最新ip数据字典中,这些地址可能按照...

    IP子网划分和可变长子网掩码VLSM解析PPT课件.pptx

    IP子网划分和可变长子网掩码VLSM解析PPT课件 本PPT课件主要讲解了IP子网划分和可变长子网掩码VLSM的相关知识。下面是对该课件中所涉及的知识点的详细解释: 1. 进制转换:二进制、十进制、十六进制和八进制之间的...

    Advanced IP Address Calculator

    2. **子网掩码与CIDR表示法**:子网掩码用于确定网络部分和主机部分,与IP地址一起用于划分子网。CIDR(无类别域间路由)是一种更加紧凑的表示子网的方法,使用斜杠(/)后面跟一个数字来表示网络前缀长度。 3. **...

    python生成IP段的方法

    2. **支持CIDR表示法**:为了更灵活地指定IP地址范围,可以添加解析CIDR表示法的功能。 - 示例:解析`192.168.1.0/24`,自动计算起始和结束地址。 3. **错误处理**:添加异常处理机制,确保程序在遇到文件操作错误...

Global site tag (gtag.js) - Google Analytics