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

目录

一、网段范围

二、思路说明

三、代码

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.mfbz.cn/a/35280.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据总线学习

为啥要数据总线 使用服务化方式发布&#xff0c;业务端和中间件完全解耦合。一处生产&#xff0c;处处消费设计理念。提供用户可定制的托管化通用消费方案&#xff08;如同步mysql到缓存&#xff0c;同步mysql到es&#xff0c;消费mysql到大数据等托管服务&#xff09; 特性 …

RabbitMQ系列(18)--RabbitMQ基于插件实现延迟队列

1、前往RabbitMQ官网下载往RabbitMQ添加延迟消息的插件 RabbitMQ官网下载插件的网址&#xff1a;https://www.rabbitmq.com/community-plugins.html 2、下载rabbitmq_delayer_message_exchange插件&#xff08;注&#xff1a;RabbitMQ是什么版本的&#xff0c;下载的插件就得是…

【UE5 Cesium】12-Cesium for Unreal 去除左下角的icon

问题 在视口左下角的icon如何去除&#xff1f; 解决方法 打开“CesiumCreditSystemBP” 将“Credit Widget Class”一项中的“ScreenCredit”替换为“ScreenCreditWidget” 编译之后icon就不显示了。

2023年5月PETS5(WSK)考试经验分享

由于本人明年打算出国联培的缘故&#xff0c;CSC国家留学基金委需要申请人的语言成绩达到一定的要求 英语&#xff08;PETS5&#xff09;&#xff1a;笔试总分55分&#xff08;含&#xff09;以上&#xff0c;其中听力部分18分&#xff08;含&#xff09;以上&#xff0c;口试…

2023最新AI创作系统/ChatGPT商业运营版网站程序源码+支持GPT4+支持ai绘画(MJ)+实时语音识别输入+免费更新版本

2023最新AI创作系统/ChatGPT商业运营版网站程序源码支持ai绘画支持GPT4.0实时语音识别输入文章资讯发布功能用户会员套餐免费更新版本 一、AI创作系统二、系统介绍三、系统程序下载四、安装教程五、主要功能展示六、更新日志 一、AI创作系统 1、提问&#xff1a;程序已经支持G…

“生鲜蔬”APP的设计与实现

1.引言 在这个科技与网络齐头并进的时代&#xff0c;外卖服务正在飞速发展&#xff0c;人们对外卖APP系统功能需求越来越多&#xff0c;开发APP的人员对自己的要求也要越来越高&#xff0c;要从所做APP外卖系统所实现的功能和用户的需求来对系统进行设计&#xff0c;还需要与当…

2023年船舶、海洋与海事工程国际会议(NAOME 2023) | Ei Scopus双检索

会议简介 Brief Introduction 2023年船舶、海洋与海事工程国际会议(NAOME 2023) 会议时间&#xff1a;2023年10月20日-22日 召开地点&#xff1a;中国镇江 大会官网&#xff1a;NAOME 2023-2023 International Conference on Naval Architecture and Ocean & Marine Engine…

腾讯云对象存储联合DataBend云数仓打通数据湖和数据仓库

随着数字化进程不断深入&#xff0c;数据呈大规模、多样性的爆发式增长。为满足更多样、更复杂的业务数据处理分析的诉求&#xff0c;湖仓一体应运而生。在Gartner发布的《Hype Cycle for Data Management 2021》中&#xff0c;湖仓一体&#xff08;Lake house&#xff09;首次…

ModaHub魔搭社区:基于阿里云 ACK 搭建开源向量数据库 Milvus

目录 一、准备资源 二、集群创建&#xff1a; 本集群基于Terway网络构建 二、连接刚刚创建的ACK集群 三、部署Milvus数据库 四、优化Milvus配置 简介&#xff1a; 生成式 AI&#xff08;Generative AI&#xff09;引爆了向量数据库&#xff08;Vector Database&#xff0…

【链表OJ】删除链表中重复的结点

⭐️ 往期链表相关OJ &#x1f4ab;链接1&#xff1a;链表分割 &#x1f4ab;链接2&#xff1a;链表中倒数第k个结点(快慢指针问题) &#x1f4ab;链接3&#xff1a;leetcode 876.链表的中间结点(快慢指针问题) &#x1f4ab;链接4&#xff1a;leetcode 206.反转链表 &#x1…

【数据结构与算法】内排序算法比较(C\C++)

实践要求 1. 问题描述 各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶&#xff0c;或大概执行时间&#xff0c;试通过随机的数据比较各算法的关键字比较次数和关键字移动次数&#xff0c;以取得直观感受。 2. 基本要求 对以下10种常用的内部排序算法进行比较…

【mysql实践】如何查看阿里云RDS的MySQL库中的binlog日志

背景&#xff1a; 工作中我们为了查看MySQL中数据修改的历史记录时&#xff0c;会通过查看binlog日志。但由于binlog日志是二进制文件&#xff0c;需要解析之后&#xff0c;才能用文本查看工具打开。这次笔者使用flink进行实时统计时就多次遇到了这个问题。经常看笔者最近博客…

redhat6安装mysql8.0.33

1、下载mysql 官网地址&#xff1a;https://downloads.mysql.com/archives/community/ 下载步骤&#xff1a; 过滤操作系统版本 下载后&#xff0c;上传到服务器Downloads目录 2、安装mysql8 解压压缩包 tar -xvf mysql-8.0.31-1.el9.x86_64.rpm-bundle.tar [rootrhel64 …

山海鲸Cesium:帮你用更简单的方式升级视效

CesiumJS作为绝大多数人都在用的开源地球可视化引擎&#xff0c;视觉效果并不拔尖&#xff0c;这让很多giser都想着有一天升级一下视效&#xff0c;从众多平庸的项目中脱颖而出。然而&#xff0c;对于一些使用Cesium的项目来说&#xff0c;要想达到Cesium for unreal的视觉效果…

Jetson Orin Nano Developer Kit

Jetson Orin Nano Developer Kit包括Jetson Orin Nano 8GB模块&#xff0c;该模块具有NVIDIA安培GPU(具有1024个CUDA内核和32个第三代张量内核)和6核ARM CPU&#xff0c;能够运行多个并发AI应用程序管道并提供高推断性能。 开发套件载体板支持所有Jetson Orin Nano和Orin NX模块…

多层感知机与深度学习算法概述

多层感知机与深度学习算法概述 读研之前那会儿我们曾纠结于机器学习、深度学习、神经网络这些概念的异同。现在看来深度学习这一算法竟然容易让人和他的爸爸机器学习搞混…可见深度学习技术的影响力之大。深度学习&#xff0c;作为机器学习家族中目前最有价值的一种算法&#…

Java安全——安全提供者

Java安全 安全提供者 在Java中&#xff0c;安全提供者&#xff08;Security Provider&#xff09;是一种实现了特定安全服务的软件模块。它提供了一系列的加密、解密、签名、验证和随机数生成等安全功能。安全提供者基础设施在Java中的作用是为开发人员提供一种扩展和替换标准…

Java性能权威指南-总结26

Java性能权威指南-总结26 数据库性能的最佳实践异常日志 数据库性能的最佳实践 异常 Java的异常处理一直有代价高昂的坏名声。其代价确实比处理正常的控制流高一些&#xff0c;不过在大多数情况下&#xff0c;这种代价并不值得浪费精力去绕过。另一方面&#xff0c;因为异常处…

【面试】美团面试真题和答案

文章目录 前言1.线程池有几种实现方式&#xff1f;2.线程池的参数含义&#xff1f;3.锁升级的过程&#xff1f;4.i 如何保证线程安全&#xff1f;5.HashMap和ConcurrentHashMap有什么区别&#xff1f;6.Autowired和Resource区别&#xff1f;7.说说常用的设计模式8.Redis为什么这…

SpringBoot2+Vue2实战(十二)springboot一对一,一对多查询

新建数据库表 Course Data TableName("t_course") public class Course implements Serializable {private static final long serialVersionUID 1L;/*** id*/TableId(value "id", type IdType.AUTO)private Integer id;/*** 课程名称*/private String…