package mapreduce.nat;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import job.Utilities;

/**
 * 关于ip操作的工具类
 *
 * @author hjb
 *
 */
public class IPV6Util {

	 public static BigInteger ipv6ToBytesToBigInteger(String ipv6) {
	        byte[] ret = new byte[17];
	        ret[0] = 0;
	        int ib = 16;
	        boolean comFlag = false;// ipv4混合模式标记
	        if (ipv6.startsWith(":"))// 去掉开头的冒号
	            ipv6 = ipv6.substring(1);
	        if (ipv6.endsWith("::")) {
				ipv6 = ipv6+"0";
			}
	        String groups[] = ipv6.split(":");
	        for (int ig = groups.length - 1; ig > -1; ig--) {// 反向扫描
	            if (groups[ig].contains(".")) {
	                // 出现ipv4混合模式
	                byte[] temp = ipv4ToBytes(groups[ig]);
	                ret[ib--] = temp[4];
	                ret[ib--] = temp[3];
	                ret[ib--] = temp[2];
	                ret[ib--] = temp[1];
	                comFlag = true;
	            } else if ("".equals(groups[ig])) {
	                // 出现零长度压缩,计算缺少的组数
	                int zlg = 9 - (groups.length + (comFlag ? 1 : 0));
	                while (zlg-- > 0) {// 将这些组置0
	                    ret[ib--] = 0;
	                    ret[ib--] = 0;
	                }
	            } else {
	                int temp = Integer.parseInt(groups[ig], 16);
	                ret[ib--] = (byte) temp;
	                ret[ib--] = (byte) (temp >> 8);
	            }
	        }
	        return new BigInteger(ret);
	    }

	 private static byte[] ipv4ToBytes(String ipv4) {
	        byte[] ret = new byte[5];
	        ret[0] = 0;
	        // 先找到IP地址字符串中.的位置
	        int position1 = ipv4.indexOf(".");
	        int position2 = ipv4.indexOf(".", position1 + 1);
	        int position3 = ipv4.indexOf(".", position2 + 1);
	        // 将每个.之间的字符串转换成整型
	        ret[1] = (byte) Integer.parseInt(ipv4.substring(0, position1));
	        ret[2] = (byte) Integer.parseInt(ipv4.substring(position1 + 1,
	                position2));
	        ret[3] = (byte) Integer.parseInt(ipv4.substring(position2 + 1,
	                position3));
	        ret[4] = (byte) Integer.parseInt(ipv4.substring(position3 + 1));
	        return ret;
	    }

	public static BigInteger[] convertList(String ip) {
		BigInteger[] arr = new BigInteger[2];
		String tmpIp = ip.substring(0, ip.indexOf("/"));
		if (Utilities.isValidIP(tmpIp)) {
			Long[] ipToLong = Utilities.getIpLong(ip);
			arr[0] = BigInteger.valueOf(ipToLong[0]);
			arr[1] = BigInteger.valueOf(ipToLong[1]);
		} else if (Utilities.isValidIPv6(tmpIp)) {
			arr = IPV6Util.getIpv6Long(ip);
		}
		return arr;
	}

	public static BigInteger convertToBigInteger(String ip) throws Exception {
		BigInteger tmpBig = null;
		if (Utilities.isValidIP(ip)) {
			Long ipToLong1 = Utilities.ipToLong(ip);
			tmpBig = BigInteger.valueOf(ipToLong1);
		} else if (Utilities.isValidIPv6(ip)) {
			tmpBig = ipv6ToBytesToBigInteger(ip);
		}
		return tmpBig;
	}

	// 将ipv6地址转换为二进制分段(为了创造ip段写的)
	public static String fenduan(String ipv6) throws UnknownHostException {
		ipv6 = completIpv6(ipv6);
		String[] split = ipv6.split(":");
		String tmpString = "";
		if (split.length == 8) {
			for (int i = 0; i < split.length; i++) {
				String str = Long.toBinaryString(Long.valueOf(split[i], 16));
				tmpString += str + "    ";
			}
		}
		return tmpString;
	}

	public static String fenduan4(String ipv6) throws UnknownHostException {
		String[] split = ipv6.split("\\.");
		String tmpString = "";
		if (split.length == 4) {
			for (int i = 0; i < split.length; i++) {
				String str = Long.toBinaryString(Long.valueOf(split[i]));
				tmpString += str + "    ";
			}
		}
		return tmpString;
	}

	public static boolean isInRange(String ip, String cidr) {
		String[] ips = ip.split("\\.");
		int ipAddr = (Integer.parseInt(ips[0]) << 24) | (Integer.parseInt(ips[1]) << 16)
				| (Integer.parseInt(ips[2]) << 8) | Integer.parseInt(ips[3]);
		int type = Integer.parseInt(cidr.replaceAll(".*/", ""));
		int mask = 0xFFFFFFFF << (32 - type);
		String cidrIp = cidr.replaceAll("/.*", "");
		String[] cidrIps = cidrIp.split("\\.");
		int cidrIpAddr = (Integer.parseInt(cidrIps[0]) << 24) | (Integer.parseInt(cidrIps[1]) << 16)
				| (Integer.parseInt(cidrIps[2]) << 8) | Integer.parseInt(cidrIps[3]);

		return (ipAddr & mask) == (cidrIpAddr & mask);
	}

	public static boolean isBelongIpv6(String ipv6, String ipv6area) throws Exception {

//		ipv6 = completIpv6(ipv6);
		int suffix = 0;
		if (ipv6area.contains("/")) {
			suffix = Integer.parseInt(ipv6area.substring(ipv6area.indexOf("/") + 1));
			ipv6area = ipv6area.substring(0, ipv6area.indexOf("/"));
		}
		BigInteger ipv6Big = ipv6ToBytesToBigInteger(ipv6);
		BigInteger ipv6areaBig = ipv6ToBytesToBigInteger(ipv6area);

		BigDecimal ss = new BigDecimal(2);
		BigDecimal pow = ss.pow(128);
		BigInteger aa = new BigInteger(pow.toString());

		String str = aa.toString(2).replaceAll("0", "1").substring(1);
		BigInteger bb = new BigInteger(str, 2);
		String str1 = bb.shiftLeft(128 - suffix).toString(2);
		String str2 = str1.substring(128 - suffix, str1.length());

		BigInteger mask = new BigInteger(str2, 2);

		return ipv6Big.and(mask).compareTo(ipv6areaBig.and(mask)) == 0 ? true : false;
	}

	/**
	 * 将ipv6每段补齐4位
	 *
	 * @return
	 * @throws UnknownHostException
	 */
	public static String completIpv6(String ipv6) throws UnknownHostException {
		StringBuffer str = new StringBuffer();
		if (isValidIPv6(ipv6)) {
			String ip = InetAddress.getByName(ipv6).toString().replace("/", "");
			String[] info = ip.split(":");
			for (int i = 0; i < info.length; i++) {
				switch (info[i].length()) {
				case 1:
					info[i] = "000" + info[i];
					break;
				case 2:
					info[i] = "00" + info[i];
					break;
				case 3:
					info[i] = "0" + info[i];
					break;
				default:
					break;
				}
				if (i < 7) {
					str.append(info[i] + ":");
				} else {
					str.append(info[i]);
				}
			}
		}
		return str.toString();
	}

	/**
	 * 将ipv6地址转换为10进制
	 *
	 * @throws Exception
	 */

	public static BigInteger ipv6ToBigInt(String ipv6) throws Exception {
		BigInteger numip = BigInteger.ZERO;
		String completIpv6 = completIpv6(ipv6);
//		String completIpv6 = ipv6;
		if (completIpv6.endsWith(":") && completIpv6.contains(".")) {
			completIpv6 = completIpv6.replace(":", "");
		}
		if (isIpV4OrV6(completIpv6) == 4) {
			numip = BigInteger.valueOf(Utilities.ipToLong(completIpv6));
		} else if (isIpV4OrV6(completIpv6) == 6) {
			String[] split = completIpv6.split(":");
			for (int i = 0; i < split.length; i++) {
				numip = numip
						.add(BigInteger.valueOf(Long.parseLong(split[i], 16)).shiftLeft(16 * (split.length - i - 1)));
			}
		}
		return numip;
	}

	/**
	 * 将整数形式的ipv6地址转换为字符串形式
	 *
	 */
	public static String int2ipv6(BigInteger big) {

		String str = "";
		BigInteger ff = BigInteger.valueOf(0xffff);
		for (int i = 0; i < 8; i++) {
			str = big.and(ff).toString(16) + ":" + str;

			big = big.shiftRight(16);
		}
		str = str.substring(0, str.length() - 1);

		return str.replaceFirst("(^|:)(0+(:|$)){2,8}", "::");
	}

	/**
	 * 将ipv6地址压缩为最简模式 IPv6简写规范: 1) 每个IPv6地址段起始的0可以被省略; 2) 如果一段为4个零,可以简写为一个0 3)
	 * 如果有连续的多个段全为0,则可以使用::表示 注:一个地址段中只能有一个::出现,不可以出现两个及以上
	 */

	public static String ipv6Shorted(String ipv6) {
		if (isValidIPv6(ipv6)) {
			ipv6 = ipv6.substring(0, ipv6.length() - 1);
		}
		return ipv6.replaceFirst("(^|:)(0+(:|$)){2,8}", "::");

	}

	/**
	 * ipv4或ipv6字符串
	 *
	 * @return 4 :ipv4, 6:ipv6, 0:地址不对
	 * @throws Exception
	 */

	public static int isIpV4OrV6(String ipAdress) throws Exception {
		InetAddress address = InetAddress.getByName(ipAdress);
		if (address instanceof Inet4Address)
			return 4;
		else if (address instanceof Inet6Address)
			return 6;
		return 0;
	}

	/**
	 * IPv4转换为IPv6
	 */

	public static String ipv4ToIpv6(String ipv6) {
		String[] octets = ipv6.split("\\.");
		byte[] octetBytes = new byte[4];
		for (int i = 0; i < 4; ++i) {
			octetBytes[i] = (byte) Integer.parseInt(octets[i]);
		}

		byte ipv4asIpV6addr[] = new byte[16];
		ipv4asIpV6addr[10] = (byte) 0xff;
		ipv4asIpV6addr[11] = (byte) 0xff;
		ipv4asIpV6addr[12] = octetBytes[0];
		ipv4asIpV6addr[13] = octetBytes[1];
		ipv4asIpV6addr[14] = octetBytes[2];
		ipv4asIpV6addr[15] = octetBytes[3];

		return "::" + (ipv4asIpV6addr[12] & 0xff) + "." + (ipv4asIpV6addr[13] & 0xff) + "."
				+ (ipv4asIpV6addr[14] & 0xff) + "." + (ipv4asIpV6addr[15] & 0xff);

	}

	/**
	 * 判断ipv6是否合法
	 *
	 * @param ip
	 * @return
	 */
	public static boolean isValidIPv6(String ip) {
		if (ip == null || ip.trim().length() == 0) {
			return false;
		}
		String t = "^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$";
		Pattern p = Pattern.compile(t);
		Matcher macher = p.matcher(ip);
		return macher.matches();
	}

	/**
	 * 判断IPv6是否属于某个IPv6段
	 *
	 * @throws Exception
	 */

	public static boolean isBelongIpv6List(String ipv6, List<String> ipv6area) throws Exception {
		for (String iparea : ipv6area) {
			if (isBelongIpv6(ipv6, iparea)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断ip是否属于某个网段
	 *
	 * @param ip
	 * @return
	 */

	public static boolean isBelongIpareaData(BigInteger ipv6, List<BigInteger[]> data) {
		for (BigInteger[] tmp : data) {
			if ((ipv6.compareTo(tmp[0]) == 1 || ipv6.compareTo(tmp[0]) == 0)
					&& (ipv6.compareTo(tmp[1]) == -1 || ipv6.compareTo(tmp[1]) == 0)) {
				return true;
			}
		}
		return false;
	}

	public static BigInteger[] getIpv6Long(String iparea) {
		try {
			iparea = iparea.trim();
			BigInteger[] info = new BigInteger[2];
			// 判断是否是具体IP
			int index = iparea.indexOf("/");
			if (index < 0) {
				info[0] = ipv6ToBytesToBigInteger(iparea);
				info[1] = ipv6ToBytesToBigInteger(iparea);
				if (info[0] == null || info[1] == null) {
					return null;
				}
				return info;
			}
			String ipinfo = iparea.substring(0, index);
			Integer count = Integer.valueOf(iparea.substring(index + 1));
			BigInteger small = BigInteger.ZERO;
			BigInteger big = BigInteger.ZERO;
			StringBuffer mask = new StringBuffer();
			for (int i = 0; i < 128; i++) {
				if (i<count) {
					mask.append("1");
				}else {
					mask.append("0");
				}
			}
			String string = new BigInteger(mask.toString(),2).toString(10);
//			for (int i = 0; i < 128 - count; i++) {
//				double pow = Math.pow(2d, Double.valueOf(Integer.valueOf(i).toString()));
//				BigInteger tmp = BigDecimal.valueOf(pow).toBigInteger();
//				small = small.add(tmp);
//			}
//			big = BigDecimal.valueOf(Math.pow(2d, Double.valueOf("128"))).toBigInteger().subtract(small)
//					.subtract(BigInteger.valueOf(1));
////
////			info[0] = areaIp.and(big);
////			info[1] = areaIp.or(small);
			BigInteger areaIp = ipv6ToBytesToBigInteger(ipinfo);
			info[0] = areaIp.and(new BigInteger(string));
			String re = mask.substring(mask.lastIndexOf("1")+1).replace("0", "1");
			info[1] = areaIp.or(new BigInteger(new BigInteger(re.toString(),2).toString(10)).subtract(BigInteger.valueOf(1)));
			if (info[0] == null || info[1] == null) {
				return null;
			}
			return info;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 给定两个初始ip和结束ip,,计算求得CIDR IP段
	 *
	 * @param startIp
	 * @param endIp
	 * @return
	 */
	public static List<String> range2cidrlist(String startIp, String endIp) {
		long start = ipToLong(startIp);
		long end = ipToLong(endIp);

		ArrayList<String> pairs = new ArrayList<String>();
		while (end >= start) {
			byte maxsize = 32;
			while (maxsize > 0) {
				long mask = CIDR2MASK[maxsize - 1];
				long maskedBase = start & mask;

				if (maskedBase != start) {
					break;
				}

				maxsize--;
			}
			double x = Math.log(end - start + 1) / Math.log(2);
			byte maxdiff = (byte) (32 - Math.floor(x));
			if (maxsize < maxdiff) {
				maxsize = maxdiff;
			}
			String ip = Utilities.longToIP(start);
			pairs.add(ip + "/" + maxsize);
			start += Math.pow(2, (32 - maxsize));
		}
		return pairs;
	}

	public static final int[] CIDR2MASK = new int[] { 0x00000000, 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,
			0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, 0xFFF80000,
			0xFFFC0000, 0xFFFE0000, 0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800, 0xFFFFFC00,
			0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
			0xFFFFFFFF };

	private static long ipToLong(String strIP) {
		long[] ip = new long[4];
		String[] ipSec = strIP.split("\\.");
		for (int k = 0; k < 4; k++) {
			ip[k] = Long.valueOf(ipSec[k]);
		}

		return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
	}
}

  

ipv6工具类的更多相关文章

  1. .net使用正则表达式校验、匹配字符工具类

    开发程序离不开数据的校验,这里整理了一些数据的校验.匹配的方法: /// <summary> /// 字符(串)验证.匹配工具类 /// </summary> public c ...

  2. 验证工具类 - ValidateUtils.java

    验证工具类,提供验证email格式.是否ipv4.是否ipv6.是否中文.是否数字.正则表达式验证的方法. 源码如下:(点击下载 - ValidateUtils.java .commons-lang- ...

  3. ios - 工具类

    这几天看项目,把俺旁边小哥哥的一个工具类相中了,希望对大家有所帮助哦~~~~~~~~~ // // PLZ_Tool.h // // Created by penglaizhi on 2017/7/3 ...

  4. Java基础Map接口+Collections工具类

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  5. Android—关于自定义对话框的工具类

    开发中有很多地方会用到自定义对话框,为了避免不必要的城府代码,在此总结出一个工具类. 弹出对话框的地方很多,但是都大同小异,不同无非就是提示内容或者图片不同,下面这个类是将提示内容和图片放到了自定义函 ...

  6. [转]Java常用工具类集合

    转自:http://blog.csdn.net/justdb/article/details/8653166 数据库连接工具类——仅仅获得连接对象 ConnDB.java package com.ut ...

  7. js常用工具类.

    一些js的工具类 复制代码 /** * Created by sevennight on 15-1-31. * js常用工具类 */ /** * 方法作用:[格式化时间] * 使用方法 * 示例: * ...

  8. Guava库介绍之实用工具类

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文是我写的Google开源的Java编程库Guava系列之一,主要介 ...

  9. Java程序员的日常—— Arrays工具类的使用

    这个类在日常的开发中,还是非常常用的.今天就总结一下Arrays工具类的常用方法.最常用的就是asList,sort,toStream,equals,copyOf了.另外可以深入学习下Arrays的排 ...

随机推荐

  1. 网页音乐播放器javascript实现,可以显示歌词

    可以显示歌词,但是歌词和歌曲都要实现自己下载下来.只能播放一首歌,歌词还得是lrc格式的代码写的很罗嗦,急切希望帮改改CSS的代码​1.代码:<html >    <head> ...

  2. NSString字符串截取方法

    1.字符串 1> 字符串比较 NSString *a = @“hello”; NSString *b = [NSString stringWithFormat:@hello”]; if (a = ...

  3. I.MX6 AW-NB177NF wifi reset

    /*********************************************************************** * I.MX6 AW-NB177NF wifi res ...

  4. 并不对劲的bzoj4012:loj2116:p3241: [HNOI2015]开店

    题目大意 有一棵\(n\)(\(n\leq1.5*10^5\))个节点的二叉树,有点权\(x\),边权\(w\),\(q\)(\(q\leq2*10^5\))组询问,每组询问给出\(u,l,r\),求 ...

  5. list:[::5]

    0-99的数列 L = [0, 1, 2, 3, ..., 99] 所有数,每5个取一个 >>> L[::5] [0, 5, 10, 15, 20, 25, 30, 35, 40, ...

  6. [转]如何用git将项目代码上传到github

    注册账户以及创建仓库 要想使用github第一步当然是注册github账号了.之后就可以创建仓库了(免费用户只能建公共仓库),Create a New Repository,填好名称后Create,之 ...

  7. 13_传智播客iOS视频教程_OC程序的编译链接

    C程序的编译.链接.执行怎么来的?在.C文件里面写上符合C语言部分的源代码.OC也是一样的.记住:OC程序的后缀名是.m. 为什么要链接?第一个.o的目标文件里面它启动不了.因为它没有启动代码我们要加 ...

  8. JS 数据类型入门与typeof操作符

    标准的数据类型划分: 基本类型: number(数字).string(字符串).undefined.boolean(布尔值).null(空对象) //空对象与非空对象,最大的区别就是不能进行属性操作 ...

  9. Docker的基础知识与安装(Ubantu CentOS)

    Docker是一种允许特殊类型虚拟化的实用程序.Docker允许使用Docker镜像在系统上“虚拟”运行程序.可以下载或创建可以运行的图像.一旦加载并执行了图像,它现在就是一个容器.容器已为容器内的程 ...

  10. [SDOI2013]保护出题人

    题目 出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了. 参加SDOI2012的小朋友们释放出大量的僵尸,企图攻击铭铭的家.而你作为SDOI2013的参赛者 ...