• IP段转为CIDR格式,自我感觉是最优解


    项目需求,给定一个IP段,转为CIDR格式表示。

    算法思想参照:http://blog.sina.com.cn/s/blog_b1e0018a0102wjdu.html ,加入我自己的理解稍作改动,实现IP段到CIDR的转换。

    例如:给定 192.168.6.73  -  192.168.6.132

       转换为:

        192.168.6.73/32

        192.168.6.74/31

        192.168.6.76/30

        192.168.6.80/28    

        192.168.6.96/27

        192.168.6.128/30

        192.168.6.132/32
     
    废话不多说,直接上代码:
    package com.comment.test;
    
    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    import java.text.DecimalFormat;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * ip 转掩码位
     *
     */
    public class Yanma {
    
        public static void main(String[] args) throws UnknownHostException {
            List<String> list = new ArrayList<>();
            run("1.1.1.1","1.1.2.32",list);
    
            list.forEach(li ->{
                System.out.println(li);
            });
        }
    
        /**
         * 二进制转换ip
         * @param strIp
         * @return
         */
        public static String longToIp(String strIp){
            int ip_1 = Integer.parseInt(strIp.substring(0, 8), 2);
            int ip_2 = Integer.parseInt(strIp.substring(8, 16), 2);
            int ip_3 = Integer.parseInt(strIp.substring(16, 24), 2);
            int ip_4 = Integer.parseInt(strIp.substring(24, 32), 2);
            return ip_1 + "." + ip_2 + "." +ip_3 + "." + ip_4;
        }
    
        /**
         * ip + 1
         * @param strIp
         * @return
         */
        public static String ipAdd(String strIp){
            String[] split = strIp.split("\.");
            int ip_1 = Integer.valueOf(split[0]);
            int ip_2 = Integer.valueOf(split[1]);
            int ip_3 = Integer.valueOf(split[2]);
            int ip_4 = Integer.valueOf(split[3]);
            // ip_4  + 1
            if(++ip_4 > 255){
                ip_4 = 0;
                if(++ip_3 > 255){
                    ip_3 = 0;
                    if(++ip_2 > 255){
                        ip_2 = 0;
                        if(++ip_1 > 255){
                            ip_1 = 0;
                        }
                    }
                }
            }
    
            return ip_1 + "." + ip_2 + "." +ip_3 + "." + ip_4;
        }
    
        /**
         * ip段范围的 网段
         * @param startIp
         * @param endIp
         * @param networkList
         * @return
         * @throws UnknownHostException
         */
        public static List<String> run(String startIp, String endIp, List<String> networkList) throws UnknownHostException {
            DecimalFormat decimalFormat = new DecimalFormat("00000000000000000000000000000000");
            // 开始ip
            byte[] startByte = InetAddress.getByName(startIp).getAddress();
            String startStr = decimalFormat.format(new BigDecimal(new BigInteger(1, startByte).toString(2)));
            // 结束ip
            byte[] endByte = InetAddress.getByName(endIp).getAddress();
            String endStr = decimalFormat.format(new BigDecimal(new BigInteger(1, endByte).toString(2)));
            // startIp == endIp
            if(startIp.equals(endIp)){
                networkList.add(startIp + "/32");
                return networkList;
            }
    
            if((startStr).compareTo(endStr) > 0) {
                return networkList;
            }
    
            // 最短掩码
            int net = startStr.lastIndexOf("1") + 1;
            for(int i = net; i <= 32; i++){
                // startip/net 表示的最大ip地址
                String substring = startStr.substring(0, i);
                String replace = startStr.substring(i).replace("0", "1");
                // 最大ip
                String maxNetwork = longToIp(substring + replace);
                // 如果最大ip小于end
                if((substring + replace).compareTo(endStr) < 0 || i == 32) {
                    networkList.add(startIp + "/" + i);
                    // ip + 1
                    run(ipAdd(maxNetwork), endIp, networkList);
                    break;
                }
            }
    
            return networkList;
        }
    
    }

    运行结果:

    示例一:

    192.168.6.73  -  192.168.6.132

    示例二:

    1.1.1.32 - 1.1.2.132

     

     举个计算过程的例子:

    使用了递归来实现。
    首先截止条件是 startip >= endip
    startip = endip 的时候向集合添加当前ip/32
    
    分解每一步的操作,以192.168.6.73-192.168.6.132 为例:
    	
    	第一次计算:
    		startip = 192.168.6.73 startStr = 11000000 10101000 00000110 01001001
    		最后一个 1 出现的位置是32
    		192.168.6.73/32 表示自己 192.168.6.73 ,符合小于结束ip 192.168.6.132 
    		所以第一次计算得到CIDR:192.168.6.73/32 表示的范围是:192.168.6.73 - 192.168.6.73
    	
    	第二次计算:
    		startip = 192.168.6.74 startStr = 11000000 10101000 00000110 01001010
    		最后一个 1 出现的位置是31
    		192.168.6.74/31 表示最大为 192.168.6.75 ,符合小于结束ip 192.168.6.132 
    		所以第二次计算得到CIDR:192.168.6.73/31 表示的范围是:192.168.6.74 - 192.168.6.75
    	
    	第三次计算:
    		startip = 192.168.6.76 startStr = 11000000 10101000 00000110 01001100
    		最后一个 1 出现的位置是30
    		192.168.6.76/30 表示最大为 192.168.6.79 ,符合小于结束ip 192.168.6.132 
    		所以第三次计算得到CIDR:192.168.6.76/30 表示的范围是:192.168.6.76 - 192.168.6.79
    		
    	第四次计算:
    		startip = 192.168.6.80 startStr = 11000000 10101000 00000110 01010000
    		最后一个 1 出现的位置是28
    		192.168.6.80/28 表示最大为 192.168.6.95 ,符合小于结束ip 192.168.6.132 
    		所以第四次计算得到CIDR:192.168.6.80/28 表示的范围是:192.168.6.80 - 192.168.6.95
    		
    	第五次计算:
    		startip = 192.168.6.96 startStr = 11000000 10101000 00000110 01100000
    		最后一个 1 出现的位置是27
    		192.168.6.96/27 表示最大为 192.168.6.127 ,符合小于结束ip 192.168.6.132 
    		所以第五次计算得到CIDR:192.168.6.96/27 表示的范围是:192.168.6.96 - 192.168.6.127
    	
    	第六次计算:
    		startip = 192.168.6.128 startStr = 11000000 10101000 00000110 10000000
    		最后一个 1 出现的位置是25
    		192.168.6.128/25 表示最大为 192.168.6.255 ,不符合小于结束ip 192.168.6.132 
    		所以 掩码位 25 不合适 ,往后推一位 26
    		192.168.6.128/26 表示最大为 192.168.6.191 ,不符合小于结束ip 192.168.6.132 
    		所以 掩码位 26 不合适 ,往后推一位 27
    		192.168.6.128/27 表示最大为 192.168.6.159 ,不符合小于结束ip 192.168.6.132 
    		所以 掩码位 27 不合适 ,往后推一位 28
    		192.168.6.128/28 表示最大为 192.168.6.143 ,不符合小于结束ip 192.168.6.132
    		所以 掩码位 28 不合适 ,往后推一位 29
    		192.168.6.128/29 表示最大为 192.168.6.135 ,不符合小于结束ip 192.168.6.132
    		所以 掩码位 29 不合适 ,往后推一位 30
    		192.168.6.128/30 表示最大为 192.168.6.131 ,符合小于结束ip 192.168.6.132
    		所以第六次计算得到CIDR:192.168.6.128/30 表示的范围是:192.168.6.128 - 192.168.6.131
    		
    	第七次计算:
    		startip = 192.168.6.132 startStr = 11000000 10101000 00000110 10000100
    		startip = endip 符合截止条件
    		计算结果为:192.168.6.132/32
    		
    	递归结束计算
    

      

  • 相关阅读:
    剑指offer——其三
    剑指offer——其二
    剑指offer——其一
    数的读法 蓝桥杯练习题 Java
    2017小结及遇见更好的2018
    自然语言处理随笔(一)
    Shell实现Windows回收站功能
    解决win7下vc6.0打开添加文件错误 崩溃
    Could not load file or assembly Microsoft.Data.OData Version=5.2.0.0 error in Azure Cloud Worker Role using Table Storage
    String两种实例化方法的区别
  • 原文地址:https://www.cnblogs.com/dongxiucai/p/13804760.html
Copyright © 2020-2023  润新知