java 计算网段范围 分析网段包含关系

news2024/11/16 8:38:51

目录

一、网段范围

二、思路说明

三、代码

1、将一个ip转为数字

2、转换子网掩码(255.255.255.0  转为  24)

3、根据 ip 与 掩码 计算最大值和最小值

4、测试

5、完整代码

四、难点讲解

1、转换子网掩码, 例:255.255.255.0  转为  24

2、根据 ip 与 掩码 的二进制 计算最大值和最小值


一、网段范围

大家在开发过程中可能会遇到对比网段的逻辑,让我们先来了解了解常见的网段范围写法

第一种   192.168.0.0-192.168.0.255

第二种   192.168.0.222  255.255.255.0

第三种   192.168.0.222/24

二、思路说明

如果一个ip可以用一个数字表示,那么就可以把一个网段范围用一个数字范围表示,这样就可以直接用大于小于等于来对比,听起来是不是很简单!

我们知道在判断时,将网段ip转为二进制 , 子网掩码也转为二进制, 然后将对比的ip也转为二进制,若(网段ip二进制每一位 并 子网掩码二进制 ) 等于 (对比的ip二进制每一位 并 子网掩码二进制),则该该ip 在网段范围中,反之则不在网段范围中。

所以,将一个ip用数字表示,可以先转为二进制,然后根据掩码算出最大最小的二进制值,然后就可以转回十进制进行对比了。

将网段ip 转为二进制(如下图,192.168.0.222 用数字 3232235742 代表)

前面说的第一种网段范围情况:直接用横杠分割,根据第一个得出最小值,根据第二个得出最大值

前面说的第二种网段范围情况:将子网掩码转成一个数字,第三种一样处理

前面说的第三种网段范围情况:最小值根据掩码将二进制可变位变为零,最大值根据掩码将二进制可变位变为零

三、代码

1、将一个ip转为数字

    public static BigInteger getBigIntegerByip(String ip) {

        BigInteger result = BigInteger.ZERO;

        String[] addrSegments = ip.split("\\.");
        for(int i = 0; i < 4; i++){
            //ip以 "点" 分成4个数, 第一个数左移24位, 第二个数左移16位, 第三个数左移8位,第四个不移,将它们相加
            BigInteger bigInteger = BigInteger.valueOf(Long.parseLong(addrSegments[i]))
                    .shiftLeft(8 * (3 - i));
            result = result.add(bigInteger);
        }

        return result;

    }

2、转换子网掩码(255.255.255.0  转为  24)

    private static IpRangeData getIpRangeDataByMask(String ipSubnetMask) {

        String[] split = ipSubnetMask.split(" ");

        String binaryMask = subnetMaskToBinary(split[1]);

        int zero = binaryMask.indexOf("0");
        int one = binaryMask.lastIndexOf("1");

        if(zero != -1 && one != -1 && zero < one) {
            //反掩码情况
            return null;
        }

        return getIpRangeDataByMask(split[0], zero == -1 ? 32 : zero);

    }

3、根据 ip 与 掩码 计算最大值和最小值

    private static IpRangeData getIpRangeDataByMask(String ip, int mask) {

        int varBin = 32 - mask;

        BigInteger bigIntegerByip = getBigIntegerByip(ip);

        BigInteger min = bigIntegerByip.shiftRight(varBin).shiftLeft(varBin);

        BigInteger varFulll = BigInteger.ONE.shiftLeft(varBin).subtract(BigInteger.ONE);

        BigInteger max = min.add(varFulll);

        IpRangeData result = new IpRangeData();
        result.setStart(min);
        result.setEnd(max);

        return result;

    }

4、测试

 

 

 

5、完整代码


import java.math.BigInteger;

/**
 * ip工具类
 *
 * @author zenglingyao
 * @date 2023/07/03
 */
public class IpUtil {

    public static BigInteger getBigIntegerByip(String ip) {

        BigInteger result = BigInteger.ZERO;

        String[] addrSegments = ip.split("\\.");
        for(int i = 0; i < 4; i++){
            //ip以 "点" 分成4个数, 第一个数左移24位, 第二个数左移16位, 第三个数左移8位,第四个不移,将它们相加
            BigInteger bigInteger = BigInteger.valueOf(Long.parseLong(addrSegments[i]))
                    .shiftLeft(8 * (3 - i));
            result = result.add(bigInteger);
        }

        return result;

    }

    /**
     * 解析网段
     *
     * @param segment 段
     * @return {@link IpRangeData}
     */
    public static IpRangeData parseSegment(String segment) {

        String trim = segment.trim();
        if (trim.contains("-")) {

            return getIpRangeDataByRange(trim);

        }else if (trim.contains("/")) {

            String[] split = trim.split("/");
            return getIpRangeDataByMask(split[0], Integer.parseInt(split[1]));

        }else {

            return getIpRangeDataByMask(segment);

        }

    }

    private static IpRangeData getIpRangeDataByRange(String ipRange) {

        String[] split = ipRange.split("-");
        String startIp = split[0];
        String endIp = split[1];

        IpRangeData result = new IpRangeData();
        result.setStart(getBigIntegerByip(startIp));
        result.setEnd(getBigIntegerByip(endIp));

        return result;

    }


    private static IpRangeData getIpRangeDataByMask(String ipSubnetMask) {

        String[] split = ipSubnetMask.split(" ");

        String binaryMask = subnetMaskToBinary(split[1]);

        int zero = binaryMask.indexOf("0");
        int one = binaryMask.lastIndexOf("1");

        if(zero != -1 && one != -1 && zero < one) {
            //反掩码情况
            return null;
        }

        return getIpRangeDataByMask(split[0], zero == -1 ? 32 : zero);

    }


    private static String subnetMaskToBinary(String subnetMask) {

        String[] split = subnetMask.split("\\.");

        StringBuilder result = new StringBuilder();

        for (String subnetMaskArr : split) {

            int decimal = Integer.parseInt(subnetMaskArr);

            StringBuilder target = new StringBuilder();
            for (int i = 0; i < 8; i++) {
                target.insert(0, decimal % 2);
                decimal /= 2;
            }

            result.append(target);

        }

        return result.toString();
    }

    private static IpRangeData getIpRangeDataByMask(String ip, int mask) {

        int varBin = 32 - mask;

        BigInteger bigIntegerByip = getBigIntegerByip(ip);

        BigInteger min = bigIntegerByip.shiftRight(varBin).shiftLeft(varBin);

        BigInteger varFulll = BigInteger.ONE.shiftLeft(varBin).subtract(BigInteger.ONE);

        BigInteger max = min.add(varFulll);

        IpRangeData result = new IpRangeData();
        result.setStart(min);
        result.setEnd(max);

        return result;

    }



    public static void main(String[] args) {

        //32位掩码情况
        String ipMask1 = "192.168.0.1/32";
        String ipSubnetMask1 = "192.168.0.1 255.255.255.255";
        String ipRange1 = "192.168.0.1-192.168.0.1";
        //0位掩码情况
        String ipMask2 = "192.168.0.1/0";
        String ipSubnetMask2 = "192.168.0.1 0.0.0.0";
        String ipRange2 = "0.0.0.0-255.255.255.255";
        //正常掩码情况1
        String ipMask3 = "192.168.0.1/24";
        String ipSubnetMask3 = "192.168.0.1 255.255.255.0";
        String ipRange3 = "192.168.0.0-192.168.0.255";
        //正常掩码情况2
        String ipMask4 = "192.168.0.1/26";
        String ipSubnetMask4 = "192.168.0.1 255.255.255.192";
        String ipRange4 = "192.168.0.192-192.168.0.63";
        //反掩码情况
        String ipSubnetMask5 = "192.168.0.1 255.255.255.247";


        System.out.println("\r\n--------32位掩码情况--------");
        System.out.println(parseSegment(ipMask1));
        System.out.println(parseSegment(ipSubnetMask1));
        System.out.println(parseSegment(ipRange1));


        System.out.println("\r\n---------0位掩码情况--------");
        System.out.println(parseSegment(ipMask2));
        System.out.println(parseSegment(ipSubnetMask2));
        System.out.println(parseSegment(ipRange2));


        System.out.println("\r\n--------正常掩码情况1--------");
        System.out.println(parseSegment(ipMask3));
        System.out.println(parseSegment(ipSubnetMask3));
        System.out.println(parseSegment(ipRange3));


        System.out.println("\r\n--------正常掩码情况2--------");
        System.out.println(parseSegment(ipMask4));
        System.out.println(parseSegment(ipSubnetMask4));
        System.out.println(parseSegment(ipRange4));


        System.out.println("\r\n---------反掩码情况---------");
        System.out.println(parseSegment(ipSubnetMask5));


    }

}


class IpRangeData {

    BigInteger start;
    BigInteger end;

    public BigInteger getStart() {
        return start;
    }

    public void setStart(BigInteger start) {
        this.start = start;
    }

    public BigInteger getEnd() {
        return end;
    }

    public void setEnd(BigInteger end) {
        this.end = end;
    }

    @Override
    public String toString() {
        return "开始值为:" + start + ", 结束值为" + end;
    }
}

四、难点讲解

1、转换子网掩码, 例:255.255.255.0  转为  24

①将 255.255.255.0 先转为  1111 1111   1111 1111    1111 1111      0000 0000

②判断第一个0与最后一个1的位置关系是否正确(判断是否反掩码),第一个0下标为结果

2、根据 ip 与 掩码 的二进制 计算最大值和最小值

①最小值

可变位全为0时最小,比如最后5位是可变位,先右移5位(最右面的5位无论是0还是1都没了),再左移5位(最右面加回来五个0)

②最大值

可变位全为1时最大,比如最后5位是可变位,前面得到的最小值加5个1就行了,如何得到5个1对应的数,把1左移5位 得到 100000 ,这个数减1 得  11111

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【习题之Python篇】习题24——回文

问题描述 2020年春节期间&#xff0c;有一个特殊的日期引起了大家的注意&#xff1a;2020年2月2日。因为如果将这个日期按 yyyymmdd 的格式写成一个8位数是 &#xff0c;恰好是一个回文数。我们称这样的日期是回文日期。 有人表示 是“千年一遇”的特殊日子。对此小明很不认同…

JavaWeb 速通CSS

目录 一、CSS入门 1.基本介绍 : 2.CSS的作用 : 3.CSS的语法 : 二、CSS样式 1.字体颜色&#xff1a; 1 说明 2 演示 2.边框 : 1 说明 2 演示 3.背景颜色 : 1 说明 2 演示 4.字体样式 : 1 说明 2 演示 5.div块居中 : 1 说明 2 演示 6.div文本居中 : 1 说明 2 演示 7.超…

【软件测试】Git详细-获取Git仓库,全网最全一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 官方提供了两种获…

GCC is no longer supported解决方法Android Studio

先说解决办法&#xff1a; 找到 -DANDROID_TOOLCHAINgcc进行删除。 原因是NDK版本过高了&#xff0c;r13b开始&#xff0c;llvm / Clang成为默认工具链&#xff0c;r18b开始删除了gcc。 删掉-DANDROID_TOOLCHAINgcc后&#xff0c;构建系统会默认使用clang。

最大流?费用流?结合二分图?例题

最大流 给出起点&#xff0c;终点&#xff0c;与边&#xff0c;边有最大流量限制&#xff0c;问从起点在不超过边的流量限制的情况下最大能从起点流多少流量到终点 反悔思想&#xff1a;如果我们每次找到一条路径就把这条路径上流量最小的边删去直到没有路径连接起点和终点&am…

飞行动力学 - 第5节-part3-爬升性能随高度的变化趋势 之 基础点摘要

飞行动力学 - 第5节-part3-爬升性能随高度的变化趋势 之 基础点摘要 1. 动力学方程2. 爬升角、爬升率趋势3. 参考资料 1. 动力学方程 回顾下&#xff0c;根据牛顿第一运动定律给出的动力学方程&#xff1a; 2. 爬升角、爬升率趋势 从推导公式的角度&#xff0c;上述趋势需要考…

按下数实融合的加速键,新华三推动基础设施变革

去年底&#xff0c;生成式AI&#xff08;AIGC&#xff09;开始席卷全球&#xff0c;吸引社会各界的广泛关注。 正所谓AI黄金时代的到来&#xff0c;将重新定义各行各业。AIGC热浪来袭&#xff0c;标志着在数实融合的大趋势下&#xff0c;人工智能大范围应用的奇点已经来临&…

Excel转图片(Java方式)

先看效果、先看效果、先看效果 左侧&#xff1a;Excel的截图 右侧&#xff1a;生成的图片 开发工具&#xff1a; Eclipse 开发环境&#xff1a; JDK1.8 使用技术&#xff1a; Graphics2D&#xff1a;&#xff08;JDK自带&…

使用python调用ChatGPT API 简单示例

如果你已经获得了OpenAI的API密钥&#xff0c;并且想要使用Python发起ChatGPT对话&#xff0c;你可以使用OpenAI的Python SDK来实现。下面是一个简单的示例代码&#xff1a; 首先&#xff0c;你需要确保已安装OpenAI的Python SDK。你可以使用pip来安装&#xff1a; pip insta…

模板(上)

文章目录 泛型编程函数模板类模板 一、泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础。 void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& …

什么是混合云?

混合云&#xff08;Hybrid Cloud&#xff09;是指结合了私有云和公有云的计算环境。私有云是指在企业内部建立的基础设施&#xff0c;由企业自己管理和控制&#xff1b;而公有云是由第三方云服务提供商&#xff08;如亚马逊AWS、微软Azure、谷歌云等&#xff09;提供的计算资源…

浅谈无效化一个空窗口的后果

有时候&#xff0c;你可能会注意到这样一个现象&#xff1a;桌面上的所有窗口都刷新了自身并产生了闪烁。 导致这个现象的原因之一是一个所谓的空句柄窗口 Bug。 如果你研究过 Win32 SDK 编程&#xff0c;则你应该比较熟悉这个函数&#xff1a;InvalidateRect。 调用这个函数可…

C# PaddleInference 图片旋转角度检测

效果 项目 VS2022.net4.8 OpenCvSharp4Sdcb.PaddleInference 代码 using OpenCvSharp; using Sdcb.PaddleInference; using Sdcb.PaddleInference.Native; using System; using System.Drawing; using System.Globalization; using System.Linq; using System.Runtime.Interop…

14天学会:基于J2EE的JAVA WEB基础

系列文章 手把手教你&#xff1a;基于Django的新闻文本分类可视化系统&#xff08;文本分类由bert实现&#xff09; 手把手教你&#xff1a;基于python的文本分类&#xff08;sklearn-决策树和随机森林实现&#xff09; 手把手教你&#xff1a;岩石样本智能识别系统 一、学习…

港联证券|股票长线投资技巧?

股票长线出资主要是看股票长时间的开展&#xff0c;所以主张从以下几个方面来剖析&#xff1a; 1、经济环境 把握宏观经济大势。股市是宏观经济的风向标&#xff0c;它在宏观经济的大环境中开展&#xff0c;而且经济的变动趋势也会影响长时间出资的收益。假如出资者能够把握住…

【java】修改JsonObject中的属性值

Java修改JsonObject中的属性值 <!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.16</version></dependency>例子 public static void m…

设计师都在找的在线SVG编辑工具!赶快收藏

为了方便设计师编辑和修改SVG图形&#xff0c;本文将介绍5款易于使用的在线SVG编辑工具&#xff0c;一起来看看吧&#xff01; 1、即时设计 即时设计是一款强大的在线SVG编辑工具&#xff0c;它可以支持路径编辑、形状编辑、填充和边框编辑、文本编辑等多种编辑需求&#xff…

人工智能套装 Ai Kit 横向测评

本文涉及到的产品 1 mechArm 270 2 mycobot 280 3 mypalletizer 260 4 AI kit 主题内容 今天的文章的主题主要介绍一下跟aikit 套件搭配的三款机械臂&#xff0c;它们之间分别有什么不一样的地方。 前言 假如说你有一台机械臂的话&#xff0c;你会用它来干什么呢&#…

【Django学习】(十一)APIView_请求与响应_GenericAPIView

继承DRF中APIView之后&#xff0c;那么当前视图就具备了认证、授权、限流等功能 继承DRF中APIView之后&#xff0c;每一个实例方法中的request为Request对象 Request类拓展了Django中的HttpRequest类&#xff0c;具备很多额外优秀的功能Request类与HttpRequest类中的所有功能兼…

2022年06月份青少年软件编程Scratch图形化等级考试试卷二级真题(含答案)

2022-06 Scratch真题二级 分数&#xff1a;100 题数&#xff1a;37 一、单选题(共25题&#xff0c;共50分) 1.角色初始位置如图所示&#xff0c;下面哪个选项能让角色移到舞台的左下角&#xff1f;&#xff08; &#xff09;(2分) A. B. C. D. 2.点击绿旗&#xff0c;执…