From 0e049861ee3f2eec6a7f5273e79e57fad4e28610 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 24 Aug 2020 17:07:46 +0800 Subject: [PATCH] add Ipv4Util --- CHANGELOG.md | 3 +- .../java/cn/hutool/core/net/Ipv4Util.java | 705 ++++++++---------- .../main/java/cn/hutool/core/net/MaskBit.java | 60 ++ .../main/java/cn/hutool/core/net/NetUtil.java | 30 +- .../cn/hutool/core/thread/ThreadUtil.java | 5 +- 5 files changed, 365 insertions(+), 438 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eb3c6e4d..01d3940d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.4.1 (2020-08-20) +# 5.4.1 (2020-08-24) ### 新特性 * 【core 】 StrUtil增加firstNonXXX方法(issue#1020@Github) @@ -14,6 +14,7 @@ * 【core 】 增加PathUtil和FileNameUtil,分离FileUtil中部分方法 * 【core 】 改造IndexedComparator,增加InstanceComparator * 【extra 】 增加CglibUtil +* 【extra 】 增加Ipv4Util(pr#161@Gitee) ### Bug修复# * 【poi 】 修复ExcelBase.isXlsx方法判断问题(issue#I1S502@Gitee) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java index d16397b69..b5ec8e720 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java @@ -1,440 +1,327 @@ package cn.hutool.core.net; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Validator; import cn.hutool.core.util.StrUtil; -import java.util.*; +import java.util.ArrayList; +import java.util.List; /** - * IP地址工具类 + * IPV4地址工具类 + * + *

pr自:https://gitee.com/loolly/hutool/pulls/161

* * @author ZhuKun - * @date 2020-08-21 + * @since 5.4.1 */ public class Ipv4Util { - /** - * IP段的分割符 - */ - public static final String IP_SPLIT_MARK = "-"; + /** + * IP段的分割符 + */ + public static final String IP_SPLIT_MARK = "-"; - /** - * IP与掩码的分割符 - */ - public static final String IP_MASK_SPLIT_MARK = "/"; + /** + * IP与掩码的分割符 + */ + public static final String IP_MASK_SPLIT_MARK = "/"; - /** - * 最大掩码位 - */ - public static final int IP_MASK_MAX = 32; + /** + * 最大掩码位 + */ + public static final int IP_MASK_MAX = 32; - /** - * 格式化IP段 - * - * @param ip IP地址 - * @param mask 掩码 - * @return 返回xxx.xxx.xxx.xxx/mask的格式 - */ - public static String formatIpBlock(String ip, String mask) { - return ip + IP_MASK_SPLIT_MARK + getMaskBitByMask(mask); - } + /** + * 格式化IP段 + * + * @param ip IP地址 + * @param mask 掩码 + * @return 返回xxx.xxx.xxx.xxx/mask的格式 + */ + public static String formatIpBlock(String ip, String mask) { + return ip + IP_MASK_SPLIT_MARK + getMaskBitByMask(mask); + } - /** - * 智能转换IP地址集合 - * - * @param ipRange IP段,支持X.X.X.X-X.X.X.X或X.X.X.X/X - * @param isAll true:全量地址,false:可用地址;仅在ipRange为X.X.X.X/X时才生效 - * @return IP集 - */ - public static List list(String ipRange, boolean isAll) { - if (ipRange.contains(IP_SPLIT_MARK)) { - String[] range = ipRange.split(IP_SPLIT_MARK); - return list(range[0], range[1]); - } else if (ipRange.contains(IP_MASK_SPLIT_MARK)) { - String[] param = ipRange.split(IP_MASK_SPLIT_MARK); - return list(param[0], Integer.parseInt(param[1]), isAll); - } else { - List ips = new ArrayList<>(); - ips.add(ipRange); - return ips; - } - } + /** + * 智能转换IP地址集合 + * + * @param ipRange IP段,支持X.X.X.X-X.X.X.X或X.X.X.X/X + * @param isAll true:全量地址,false:可用地址;仅在ipRange为X.X.X.X/X时才生效 + * @return IP集 + */ + public static List list(String ipRange, boolean isAll) { + if (ipRange.contains(IP_SPLIT_MARK)) { + String[] range = ipRange.split(IP_SPLIT_MARK); + return list(range[0], range[1]); + } else if (ipRange.contains(IP_MASK_SPLIT_MARK)) { + String[] param = ipRange.split(IP_MASK_SPLIT_MARK); + return list(param[0], Integer.parseInt(param[1]), isAll); + } else { + List ips = new ArrayList<>(); + ips.add(ipRange); + return ips; + } + } - /** - * 根据IP地址、子网掩码获取IP地址区间 - * - * @param ip IP地址 - * @param maskBit 掩码位,例如24、32 - * @param isAll true:全量地址,false:可用地址 - * @return - */ - public static List list(String ip, int maskBit, boolean isAll) { - List list = new ArrayList<>(); - if (maskBit == IP_MASK_MAX) { - if (Boolean.TRUE.equals(isAll)) { - list.add(ip); - } - } else { - String startIp = getBeginIpStr(ip, maskBit); - String endIp = getEndIpStr(ip, maskBit); - String subStart = startIp.split("\\.")[0] + "." + startIp.split("\\.")[1] + "." + startIp.split("\\.")[2] + "."; - String subEnd = endIp.split("\\.")[0] + "." + endIp.split("\\.")[1] + "." + endIp.split("\\.")[2] + "."; - if (Boolean.TRUE.equals(isAll)) { - startIp = subStart + (Integer.parseInt(startIp.split("\\.")[3])); - endIp = subEnd + (Integer.parseInt(endIp.split("\\.")[3])); - } else { - startIp = subStart + (Integer.parseInt(startIp.split("\\.")[3]) + 1); - endIp = subEnd + (Integer.parseInt(endIp.split("\\.")[3]) - 1); - } - list = list(startIp, endIp); - } - return list; - } + /** + * 根据IP地址、子网掩码获取IP地址区间 + * + * @param ip IP地址 + * @param maskBit 掩码位,例如24、32 + * @param isAll true:全量地址,false:可用地址 + * @return 区间地址 + */ + public static List list(String ip, int maskBit, boolean isAll) { + List list = new ArrayList<>(); + if (maskBit == IP_MASK_MAX) { + if (Boolean.TRUE.equals(isAll)) { + list.add(ip); + } + } else { + String startIp = getBeginIpStr(ip, maskBit); + String endIp = getEndIpStr(ip, maskBit); + String subStart = startIp.split("\\.")[0] + "." + startIp.split("\\.")[1] + "." + startIp.split("\\.")[2] + "."; + String subEnd = endIp.split("\\.")[0] + "." + endIp.split("\\.")[1] + "." + endIp.split("\\.")[2] + "."; + if (Boolean.TRUE.equals(isAll)) { + startIp = subStart + (Integer.parseInt(startIp.split("\\.")[3])); + endIp = subEnd + (Integer.parseInt(endIp.split("\\.")[3])); + } else { + startIp = subStart + (Integer.parseInt(startIp.split("\\.")[3]) + 1); + endIp = subEnd + (Integer.parseInt(endIp.split("\\.")[3]) - 1); + } + list = list(startIp, endIp); + } + return list; + } - /** - * 得到IP地址区间 - * - * @param ipFrom 开始IP - * @param ipTo 结束IP - * @return - */ - public static List list(String ipFrom, String ipTo) { - List ips = new ArrayList<>(); - String[] ipfromd = ipFrom.split("\\."); - String[] iptod = ipTo.split("\\."); - int[] int_ipf = new int[4]; - int[] int_ipt = new int[4]; - for (int i = 0; i < 4; i++) { - int_ipf[i] = Integer.parseInt(ipfromd[i]); - int_ipt[i] = Integer.parseInt(iptod[i]); - } - for (int A = int_ipf[0]; A <= int_ipt[0]; A++) { - for (int B = (A == int_ipf[0] ? int_ipf[1] : 0); B <= (A == int_ipt[0] ? int_ipt[1] - : 255); B++) { - for (int C = (B == int_ipf[1] ? int_ipf[2] : 0); C <= (B == int_ipt[1] ? int_ipt[2] - : 255); C++) { - for (int D = (C == int_ipf[2] ? int_ipf[3] : 0); D <= (C == int_ipt[2] ? int_ipt[3] - : 255); D++) { - ips.add(A + "." + B + "." + C + "." + D); - } - } - } - } - return ips; - } + /** + * 得到IP地址区间 + * + * @param ipFrom 开始IP + * @param ipTo 结束IP + * @return 区间地址 + */ + public static List list(String ipFrom, String ipTo) { + final int[] ipf = Convert.convert(int[].class, StrUtil.splitToArray(ipFrom, '.')); + final int[] ipt = Convert.convert(int[].class, StrUtil.splitToArray(ipTo, '.')); - /** - * 把long类型的Ip转为一般Ip类型:xx.xx.xx.xx - * - * @param ip - * @return - */ - public static String longIpToStr(Long ip) { - String s1 = String.valueOf((ip & 4278190080L) / 16777216L); - String s2 = String.valueOf((ip & 16711680L) / 65536L); - String s3 = String.valueOf((ip & 65280L) / 256L); - String s4 = String.valueOf(ip & 255L); - return s1 + "." + s2 + "." + s3 + "." + s4; - } + final List ips = new ArrayList<>(); + for (int a = ipf[0]; a <= ipt[0]; a++) { + for (int b = (a == ipf[0] ? ipf[1] : 0); b <= (a == ipt[0] ? ipt[1] + : 255); b++) { + for (int c = (b == ipf[1] ? ipf[2] : 0); c <= (b == ipt[1] ? ipt[2] + : 255); c++) { + for (int d = (c == ipf[2] ? ipf[3] : 0); d <= (c == ipt[2] ? ipt[3] + : 255); d++) { + ips.add(a + "." + b + "." + c + "." + d); + } + } + } + } + return ips; + } - /** - * 把xxx.xxx.xxx.xxx类型的转为long类型的IP - * - * @param ip 字符类型的IP - * @return - */ - public static Long strIpToLong(String ip) { - Long ipLong = 0L; - String ipTemp = ip; - ipLong = ipLong * 256 - + Long.parseLong(ipTemp.substring(0, ipTemp.indexOf("."))); - ipTemp = ipTemp.substring(ipTemp.indexOf(".") + 1); - ipLong = ipLong * 256 - + Long.parseLong(ipTemp.substring(0, ipTemp.indexOf("."))); - ipTemp = ipTemp.substring(ipTemp.indexOf(".") + 1); - ipLong = ipLong * 256 - + Long.parseLong(ipTemp.substring(0, ipTemp.indexOf("."))); - ipTemp = ipTemp.substring(ipTemp.indexOf(".") + 1); - ipLong = ipLong * 256 + Long.parseLong(ipTemp); - return ipLong; - } + /** + * 根据long值获取ip v4地址:xx.xx.xx.xx + * + * @param longIP IP的long表示形式 + * @return IP V4 地址 + */ + public static String longToIpv4(long longIP) { + final StringBuilder sb = StrUtil.builder(); + // 直接右移24位 + sb.append((longIP >>> 24)); + sb.append("."); + // 将高8位置0,然后右移16位 + sb.append(((longIP & 0x00FFFFFF) >>> 16)); + sb.append("."); + sb.append(((longIP & 0x0000FFFF) >>> 8)); + sb.append("."); + sb.append((longIP & 0x000000FF)); + return sb.toString(); + } - /** - * 根据掩码位获取掩码 - * - * @param maskBit 掩码位数,如"28"、"30" - * @return - */ - public static String getMaskByMaskBit(String maskBit) { - return StrUtil.isEmpty(maskBit) ? "error, maskBit is null !" - : maskBitMap().get(maskBit); - } + /** + * 根据ip地址(xxx.xxx.xxx.xxx)计算出long型的数据 + * + * @param strIP IP V4 地址 + * @return long值 + */ + public static long ipv4ToLong(String strIP) { + if (Validator.isIpv4(strIP)) { + long[] ip = new long[4]; + // 先找到IP地址字符串中.的位置 + int position1 = strIP.indexOf("."); + int position2 = strIP.indexOf(".", position1 + 1); + int position3 = strIP.indexOf(".", position2 + 1); + // 将每个.之间的字符串转换成整型 + ip[0] = Long.parseLong(strIP.substring(0, position1)); + ip[1] = Long.parseLong(strIP.substring(position1 + 1, position2)); + ip[2] = Long.parseLong(strIP.substring(position2 + 1, position3)); + ip[3] = Long.parseLong(strIP.substring(position3 + 1)); + return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3]; + } + return 0; + } - /** - * 根据 ip/掩码位 计算IP段的起始IP(字符串型) - * - * @param ip 给定的IP,如218.240.38.69 - * @param maskBit 给定的掩码位,如30 - * @return 起始IP的字符串表示 - */ - public static String getBeginIpStr(String ip, int maskBit) { - return longIpToStr(getBeginIpLong(ip, maskBit)); - } + /** + * 根据 ip/掩码位 计算IP段的起始IP(字符串型) + * + * @param ip 给定的IP,如218.240.38.69 + * @param maskBit 给定的掩码位,如30 + * @return 起始IP的字符串表示 + */ + public static String getBeginIpStr(String ip, int maskBit) { + return longToIpv4(getBeginIpLong(ip, maskBit)); + } - /** - * 根据 ip/掩码位 计算IP段的起始IP(Long型) - * - * @param ip 给定的IP,如218.240.38.69 - * @param maskBit 给定的掩码位,如30 - * @return 起始IP的长整型表示 - */ - private static Long getBeginIpLong(String ip, int maskBit) { - return strIpToLong(ip) & strIpToLong(getMaskByMaskBit(maskBit)); - } + /** + * 根据 ip/掩码位 计算IP段的起始IP(Long型) + * + * @param ip 给定的IP,如218.240.38.69 + * @param maskBit 给定的掩码位,如30 + * @return 起始IP的长整型表示 + */ + private static Long getBeginIpLong(String ip, int maskBit) { + return ipv4ToLong(ip) & ipv4ToLong(getMaskByMaskBit(maskBit)); + } - /** - * 根据 ip/掩码位 计算IP段的终止IP(字符串型) - * - * @param ip 给定的IP,如218.240.38.69 - * @param maskBit 给定的掩码位,如30 - * @return 终止IP的字符串表示 - */ - public static String getEndIpStr(String ip, int maskBit) { - return longIpToStr(getEndIpLong(ip, maskBit)); - } + /** + * 根据 ip/掩码位 计算IP段的终止IP(字符串型) + * + * @param ip 给定的IP,如218.240.38.69 + * @param maskBit 给定的掩码位,如30 + * @return 终止IP的字符串表示 + */ + public static String getEndIpStr(String ip, int maskBit) { + return longToIpv4(getEndIpLong(ip, maskBit)); + } - /** - * 根据 ip/掩码位 计算IP段的终止IP(Long型) - * 注:此接口返回负数,请使用转成字符串后再转Long型 - * - * @param ip 给定的IP,如218.240.38.69 - * @param maskBit 给定的掩码位,如30 - * @return 终止IP的长整型表示 - */ - private static Long getEndIpLong(String ip, int maskBit) { - return getBeginIpLong(ip, maskBit) - + ~strIpToLong(getMaskByMaskBit(maskBit)); - } + /** + * 根据子网掩码转换为掩码位 + * + * @param mask 掩码,例如xxx.xxx.xxx.xxx + * @return 掩码位,例如32 + */ + public static int getMaskBitByMask(String mask) { + StringBuffer sbf; + String str; + int inetmask = 0; + int count; + for (String s : StrUtil.split(mask, ',')) { + sbf = toBin(Integer.parseInt(s)); + str = sbf.reverse().toString(); + count = 0; + for (int i = 0; i < str.length(); i++) { + i = str.indexOf('1', i); + if (i == -1) { + break; + } + count++; + } + inetmask += count; + } + return inetmask; + } + /** + * 计算子网大小 + * + * @param maskBit 掩码位 + * @param isAll true:全量地址,false:可用地址 + * @return 地址总数 + */ + public static int countByMaskBit(int maskBit, boolean isAll) { + //如果是可用地址的情况,掩码位小于等于0或大于等于32,则可用地址为0 + boolean isZero = !isAll && (maskBit <= 0 || maskBit >= 32); + if (isZero) { + return 0; + } + if (isAll) { + return (int) Math.pow(2, 32 - maskBit); + } else { + return (int) Math.pow(2, 32 - maskBit) - 2; + } + } - /** - * 根据子网掩码转换为掩码位 - * - * @param mask 掩码,例如xxx.xxx.xxx.xxx - * @return 掩码位,例如32 - */ - public static int getMaskBitByMask(String mask) { - StringBuffer sbf; - String str; - int inetmask = 0, count = 0; - String[] ipList = mask.split("\\."); - for (int n = 0; n < ipList.length; n++) { - sbf = toBin(Integer.parseInt(ipList[n])); - str = sbf.reverse().toString(); - count = 0; - for (int i = 0; i < str.length(); i++) { - i = str.indexOf('1', i); - if (i == -1) { - break; - } - count++; - } - inetmask += count; - } - return inetmask; - } + /** + * 根据掩码位获取掩码 + * + * @param maskBit 掩码位 + * @return 掩码 + */ + public static String getMaskByMaskBit(int maskBit) { + return MaskBit.get(maskBit); + } - /** - * 计算子网大小 - * - * @param maskBit 掩码位 - * @param isAll true:全量地址,false:可用地址 - * @return 地址总数 - */ - public static int countByMaskBit(int maskBit, boolean isAll) { - //如果是可用地址的情况,掩码位小于等于0或大于等于32,则可用地址为0 - boolean isZero = !isAll && (maskBit <= 0 || maskBit >= 32); - if (isZero) { - return 0; - } - if (isAll) { - return (int) Math.pow(2, 32 - maskBit); - } else { - return (int) Math.pow(2, 32 - maskBit) - 2; - } - } + /** + * 根据开始IP与结束IP计算掩码 + * + * @param fromIp 开始IP + * @param toIp 结束IP + * @return 掩码x.x.x.x + */ + public static String getMaskByIpRange(String fromIp, String toIp) { + long toIpLong = ipv4ToLong(toIp); + long fromIpLong = ipv4ToLong(fromIp); + if (fromIpLong > toIpLong) { + throw new IllegalArgumentException("to IP must be greater than from IP!"); + } + String[] fromIpSplit = StrUtil.splitToArray(fromIp, '.'); + String[] toIpSplit = StrUtil.splitToArray(toIp, '.'); + StringBuilder mask = new StringBuilder(); + for (int i = 0; i < toIpSplit.length; i++) { + mask.append(255 - Integer.parseInt(toIpSplit[i]) + Integer.parseInt(fromIpSplit[i])).append("."); + } + return mask.substring(0, mask.length() - 1); + } - private static StringBuffer toBin(int x) { - StringBuffer result = new StringBuffer(); - result.append(x % 2); - x /= 2; - while (x > 0) { - result.append(x % 2); - x /= 2; - } - return result; - } + /** + * 计算IP区间有多少个IP + * + * @param fromIp 开始IP + * @param toIp 结束IP + * @return IP数量 + */ + public static int countByIpRange(String fromIp, String toIp) { + long toIpLong = ipv4ToLong(toIp); + long fromIpLong = ipv4ToLong(fromIp); + if (fromIpLong > toIpLong) { + throw new IllegalArgumentException("to IP must be greater than from IP!"); + } + int count = 1; + int[] fromIpSplit = StrUtil.split(fromIp, '.').stream().mapToInt(Integer::parseInt).toArray(); + int[] toIpSplit = StrUtil.split(toIp, '.').stream().mapToInt(Integer::parseInt).toArray(); + for (int i = fromIpSplit.length - 1; i >= 0; i--) { + count += (toIpSplit[i] - fromIpSplit[i]) * Math.pow(256, fromIpSplit.length - i - 1); + } + return count; + } - /** - * 存储着所有的掩码位及对应的掩码 key:掩码位 value:掩码(x.x.x.x) - * - * @return - */ - private static Map maskBitMap() { - Map maskBit = new HashMap<>(32); - maskBit.put("1", "128.0.0.0"); - maskBit.put("2", "192.0.0.0"); - maskBit.put("3", "224.0.0.0"); - maskBit.put("4", "240.0.0.0"); - maskBit.put("5", "248.0.0.0"); - maskBit.put("6", "252.0.0.0"); - maskBit.put("7", "254.0.0.0"); - maskBit.put("8", "255.0.0.0"); - maskBit.put("9", "255.128.0.0"); - maskBit.put("10", "255.192.0.0"); - maskBit.put("11", "255.224.0.0"); - maskBit.put("12", "255.240.0.0"); - maskBit.put("13", "255.248.0.0"); - maskBit.put("14", "255.252.0.0"); - maskBit.put("15", "255.254.0.0"); - maskBit.put("16", "255.255.0.0"); - maskBit.put("17", "255.255.128.0"); - maskBit.put("18", "255.255.192.0"); - maskBit.put("19", "255.255.224.0"); - maskBit.put("20", "255.255.240.0"); - maskBit.put("21", "255.255.248.0"); - maskBit.put("22", "255.255.252.0"); - maskBit.put("23", "255.255.254.0"); - maskBit.put("24", "255.255.255.0"); - maskBit.put("25", "255.255.255.128"); - maskBit.put("26", "255.255.255.192"); - maskBit.put("27", "255.255.255.224"); - maskBit.put("28", "255.255.255.240"); - maskBit.put("29", "255.255.255.248"); - maskBit.put("30", "255.255.255.252"); - maskBit.put("31", "255.255.255.254"); - maskBit.put("32", "255.255.255.255"); - return maskBit; - } + //-------------------------------------------------------------------------------- Private method start - /** - * 根据掩码位获取掩码 - * - * @param maskBit - * @return - */ - public static String getMaskByMaskBit(int maskBit) { - switch (maskBit) { - case 1: - return "128.0.0.0"; - case 2: - return "192.0.0.0"; - case 3: - return "224.0.0.0"; - case 4: - return "240.0.0.0"; - case 5: - return "248.0.0.0"; - case 6: - return "252.0.0.0"; - case 7: - return "254.0.0.0"; - case 8: - return "255.0.0.0"; - case 9: - return "255.128.0.0"; - case 10: - return "255.192.0.0"; - case 11: - return "255.224.0.0"; - case 12: - return "255.240.0.0"; - case 13: - return "255.248.0.0"; - case 14: - return "255.252.0.0"; - case 15: - return "255.254.0.0"; - case 16: - return "255.255.0.0"; - case 17: - return "255.255.128.0"; - case 18: - return "255.255.192.0"; - case 19: - return "255.255.224.0"; - case 20: - return "255.255.240.0"; - case 21: - return "255.255.248.0"; - case 22: - return "255.255.252.0"; - case 23: - return "255.255.254.0"; - case 24: - return "255.255.255.0"; - case 25: - return "255.255.255.128"; - case 26: - return "255.255.255.192"; - case 27: - return "255.255.255.224"; - case 28: - return "255.255.255.240"; - case 29: - return "255.255.255.248"; - case 30: - return "255.255.255.252"; - case 31: - return "255.255.255.254"; - case 32: - return "255.255.255.255"; - default: - return ""; - } - } + /** + * 根据 ip/掩码位 计算IP段的终止IP(Long型) + * 注:此接口返回负数,请使用转成字符串后再转Long型 + * + * @param ip 给定的IP,如218.240.38.69 + * @param maskBit 给定的掩码位,如30 + * @return 终止IP的长整型表示 + */ + private static Long getEndIpLong(String ip, int maskBit) { + return getBeginIpLong(ip, maskBit) + + ~ipv4ToLong(getMaskByMaskBit(maskBit)); + } - /** - * 根据开始IP与结束IP计算掩码 - * - * @param fromIp 开始IP - * @param toIp 结束IP - * @return 掩码x.x.x.x - * @throws Exception - */ - public static String getMaskByIpRange(String fromIp, String toIp) throws Exception { - Long toIpLong = strIpToLong(toIp); - Long fromIpLong = strIpToLong(fromIp); - if (fromIpLong > toIpLong) { - throw new Exception("开始IP大与结束IP"); - } - String[] fromIpSplit = fromIp.split("\\."); - String[] toIpSplit = toIp.split("\\."); - StringBuilder mask = new StringBuilder(); - for (int i = 0; i < toIpSplit.length; i++) { - mask.append(255 - Integer.parseInt(toIpSplit[i]) + Integer.parseInt(fromIpSplit[i])).append("."); - } - return mask.substring(0, mask.length() - 1); - } - - /** - * 计算IP区间有多少个IP - * - * @param fromIp 开始IP - * @param toIp 结束IP - * @return IP数量 - * @throws Exception - */ - public static int countByIpRange(String fromIp, String toIp) throws Exception { - Long toIpLong = strIpToLong(toIp); - Long fromIpLong = strIpToLong(fromIp); - if (fromIpLong > toIpLong) { - throw new Exception("开始IP大与结束IP"); - } - int count = 1; - int[] fromIpSplit = Arrays.stream(fromIp.split("\\.")).mapToInt(Integer::parseInt).toArray(); - int[] toIpSplit = Arrays.stream(toIp.split("\\.")).mapToInt(Integer::parseInt).toArray(); - for (int i = fromIpSplit.length - 1; i >= 0; i--) { - count += (toIpSplit[i] - fromIpSplit[i]) * Math.pow(256, fromIpSplit.length - i - 1); - } - return count; - } + private static StringBuffer toBin(int x) { + StringBuffer result = new StringBuffer(); + result.append(x % 2); + x /= 2; + while (x > 0) { + result.append(x % 2); + x /= 2; + } + return result; + } + //-------------------------------------------------------------------------------- Private method end } diff --git a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java new file mode 100644 index 000000000..108ee1635 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java @@ -0,0 +1,60 @@ +package cn.hutool.core.net; + +import java.util.HashMap; +import java.util.Map; + +/** + * 掩码位和掩码之间的Map对应 + * + * @since 5.4.1 + * @author looly + */ +public class MaskBit { + + private static final Map maskBitMap; + static { + maskBitMap = new HashMap<>(32); + maskBitMap.put(1, "128.0.0.0"); + maskBitMap.put(2, "192.0.0.0"); + maskBitMap.put(3, "224.0.0.0"); + maskBitMap.put(4, "240.0.0.0"); + maskBitMap.put(5, "248.0.0.0"); + maskBitMap.put(6, "252.0.0.0"); + maskBitMap.put(7, "254.0.0.0"); + maskBitMap.put(8, "255.0.0.0"); + maskBitMap.put(9, "255.128.0.0"); + maskBitMap.put(10, "255.192.0.0"); + maskBitMap.put(11, "255.224.0.0"); + maskBitMap.put(12, "255.240.0.0"); + maskBitMap.put(13, "255.248.0.0"); + maskBitMap.put(14, "255.252.0.0"); + maskBitMap.put(15, "255.254.0.0"); + maskBitMap.put(16, "255.255.0.0"); + maskBitMap.put(17, "255.255.128.0"); + maskBitMap.put(18, "255.255.192.0"); + maskBitMap.put(19, "255.255.224.0"); + maskBitMap.put(20, "255.255.240.0"); + maskBitMap.put(21, "255.255.248.0"); + maskBitMap.put(22, "255.255.252.0"); + maskBitMap.put(23, "255.255.254.0"); + maskBitMap.put(24, "255.255.255.0"); + maskBitMap.put(25, "255.255.255.128"); + maskBitMap.put(26, "255.255.255.192"); + maskBitMap.put(27, "255.255.255.224"); + maskBitMap.put(28, "255.255.255.240"); + maskBitMap.put(29, "255.255.255.248"); + maskBitMap.put(30, "255.255.255.252"); + maskBitMap.put(31, "255.255.255.254"); + maskBitMap.put(32, "255.255.255.255"); + } + + /** + * 根据掩码位获取掩码 + * + * @param maskBit 掩码位 + * @return 掩码 + */ + public static String get(int maskBit) { + return maskBitMap.get(maskBit); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java index 1c218677f..8f239c751 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java @@ -5,7 +5,6 @@ import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Filter; -import cn.hutool.core.lang.Validator; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; @@ -58,19 +57,10 @@ public class NetUtil { * * @param longIP IP的long表示形式 * @return IP V4 地址 + * @see Ipv4Util#longToIpv4(long) */ public static String longToIpv4(long longIP) { - final StringBuilder sb = StrUtil.builder(); - // 直接右移24位 - sb.append((longIP >>> 24)); - sb.append("."); - // 将高8位置0,然后右移16位 - sb.append(((longIP & 0x00FFFFFF) >>> 16)); - sb.append("."); - sb.append(((longIP & 0x0000FFFF) >>> 8)); - sb.append("."); - sb.append((longIP & 0x000000FF)); - return sb.toString(); + return Ipv4Util.longToIpv4(longIP); } /** @@ -78,22 +68,10 @@ public class NetUtil { * * @param strIP IP V4 地址 * @return long值 + * @see Ipv4Util#ipv4ToLong(String) */ public static long ipv4ToLong(String strIP) { - if (Validator.isIpv4(strIP)) { - long[] ip = new long[4]; - // 先找到IP地址字符串中.的位置 - int position1 = strIP.indexOf("."); - int position2 = strIP.indexOf(".", position1 + 1); - int position3 = strIP.indexOf(".", position2 + 1); - // 将每个.之间的字符串转换成整型 - ip[0] = Long.parseLong(strIP.substring(0, position1)); - ip[1] = Long.parseLong(strIP.substring(position1 + 1, position2)); - ip[2] = Long.parseLong(strIP.substring(position2 + 1, position3)); - ip[3] = Long.parseLong(strIP.substring(position3 + 1)); - return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3]; - } - return 0; + return Ipv4Util.ipv4ToLong(strIP); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java b/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java index 836897cba..ab8ba9ef1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java @@ -92,10 +92,11 @@ public class ThreadUtil { * 获得一个新的线程池,并指定最大任务队列大小
* 如果maximumPoolSize >= corePoolSize,在没有新任务加入的情况下,多出的线程将最多保留60s * - * @param corePoolSize 初始线程池大小 - * @param maximumPoolSize 最大线程池大小 + * @param corePoolSize 初始线程池大小 + * @param maximumPoolSize 最大线程池大小 * @param maximumQueueSize 最大任务队列大小 * @return {@link ThreadPoolExecutor} + * @since 5.4.1 */ public static ExecutorService newExecutor(int corePoolSize, int maximumPoolSize, int maximumQueueSize) { return ExecutorBuilder.create()