jdk8-获取本机ip、判断ip范围、ip与long互转等

  • Post author:
  • Post category:其他


在配置nginx的ip白名单时候,会通过ip段进行配置(如 10.10.10.10/24),就在思考这种配置怎么通过代码解析并判断,故通过搜索网络内容,并通过java编写测试代码。代码及说明来源网络,并进行了部分调整。故有疑问请提出来,本人小白一枚,勿喷

代码内容:获取本机ip、判断ip范围、ip与long互转等

IP: 网络地址

掩码: 指明一个IP地址的哪些位标识的是主机所在的子网。

网段:网络中可通信的部分,一般用子网第一个地址表示。

广播地址:专门用于同时向网络中所有工作站进行发送的一个地址;一般用子网最后一个地址表示。

可用子网ip:一般指子网中去除网段、广播地址的地址范围



参考


处理ip,java判断ip是否在指定的ip段范围内,给定的ip地址是否在某个ip段范围内,将字符串形式IP地址转换long类型



ip地址与掩码、网段、广播地址、可用ip范围



java实现 IP/掩码位 转换 ip段范围



192.168.和10.0.开头的IP、内网IP段、IP简介、分类——IP观止



JDK8 Java 中遇到null 和为空的情况,使用Optional来解决



什么是ip地址



代码



demo

代码参考自

参考

内,并进行了部分重构

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Optional;

/**
 * Ip工具类
 *
 * @author z.y.l
 * @version v1.0
 * @date 2022/12/13
 */
public class IpUtil {
    private static final int I_32 = 32;
    /** ip 255.255.255.255 >>> 11111111111111111111111111111111 */
    private static final long VALIDATE_DATA = 4294967295L;
    private static final HashMap<Integer,String> NET_MASK = new HashMap<>();
    /** 1-255 正则 */
    private static final String REG_1_255 = "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])";
    /** 0-255 正则 */
    private static final String REG_0_255 = "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)";
    /** ip 正则 */
    private static final String IP_REGEX = "^" + REG_1_255 + "\\." + REG_0_255 + "\\." + REG_0_255 + "\\." + REG_0_255 + "$";
    static {
        /* 初始化掩码 */
        NET_MASK.put( I_32, long2ip( VALIDATE_DATA ) );
        for(int i = 1 ; i < I_32 ; i++ ){
            NET_MASK.put( I_32-i, long2ip( VALIDATE_DATA << i & VALIDATE_DATA ) );
        }
    }

    public static void main(String[] args) {
        String localIp = inetIp();
        System.out.println("本机ip:"+localIp);
        System.out.println("-------------");
        System.out.println(new IpInf("192.168.1.2", "255.255.254.0").toString());
        System.out.println(new IpInf("192.168.1.3", "255.255.255.0").toString());
        System.out.println("-------------");
        String ip="10.10.10.116";
        String startIP = "10.10.1.0";
        String endIP = "10.10.255.255";
        System.out.println("ip:10.10.10.116>>>"+ip2Long(ip));
        System.out.println("ip:10.10.10.116,startIP:10.10.1.0,endIP:10.10.255.255,>>>"+ipExistsIn(ip,startIP,endIP));
        System.out.println("-------------");
        //判断一个IP是否属于某个网段
        System.out.println("ip:10.2.1.0,cip:10.2.0.0/17,>>>"+ipIsIn("10.2.1.0", "10.2.0.0/17"));
    }
    /**
     * 获取 本机ip
     * @return 本机ip
     */
    public static String inetIp(){
        try {
            Enumeration<NetworkInterface> nif = NetworkInterface.getNetworkInterfaces();
            while (nif.hasMoreElements()) {
                NetworkInterface ni = nif.nextElement();
                Enumeration<InetAddress> inet = ni.getInetAddresses();
                while (inet.hasMoreElements()) {
                    InetAddress ia = inet.nextElement();
                    if (!ia.isLinkLocalAddress() && !ia.isLoopbackAddress() && ia instanceof Inet4Address) {
                        return ia.getHostAddress();
                    }
                }
            }
        } catch (Exception e) {
            return null;
        }
        return "";
    }
    /** 判断一个ip地址是否在某个ip段范围内 */
    public static boolean ipExistsIn(String ip,String start,String end){
        long ipL = ip2Long(ip);
        return ( ip2Long(start) <= ipL ) && ( ip2Long(end) >= ipL );
    }
    /**
     * 功能:判断一个IP是不是在一个网段下的
     * 格式:isInRange("192.168.8.3", "192.168.9.10/22");
     */
    public static boolean ipIsIn(String ip,String cip){
        long ipL = ip2Long(ip);
        String[] split = cip.split("/");
        int mask = 0xFFFFFFFF << ( 32L - s2l(split[1]));
        long cipL = ip2Long(split[0]);
        return ( ipL & mask ) == ( cipL & mask );
    }
    /** 把long类型的Ip转为一般Ip类型:xx.xx.xx.xx */
    public static String long2ip(Long ip){
        Long tmp = Optional.ofNullable(ip).filter(l -> l >= 0 && l <= VALIDATE_DATA )
                .orElseThrow(()-> new RuntimeException(ip + " 数字 不在 有效ip范围."));
        // 255.0.0.0 ~ 1.0.0.0,0.255.0.0 ~ 0.1.0.0,0.0.255.0 ~ 0.0.1.0,0.0.0.255 ~ 0.0.0.1
        return (tmp>>>24) + "." + (tmp>>>16&255L) + "." + (tmp>>>8&255L) + "." + (tmp&255L);
    }
    /** 将字符串形式IP地址转换long类型 */
    public static long ip2Long(String ip){
        ip = checkIp(ip);
        String[] split = ip.trim().split("\\.");
        return ( s2l(split[0]) << 24 ) + ( s2l(split[1]) << 16 ) + ( s2l(split[2]) << 8 )+ ( s2l(split[3]) );
    }
    private static long s2l(String s){
        return Long.parseLong(s,10);
    }
    private static String checkIp(String ip){
        return Optional.ofNullable(ip).filter(s -> !s.isEmpty()&&s.matches(IP_REGEX))
                .orElseThrow(() -> new RuntimeException(ip + " ip地址不合法."));
    }
    private static String checkMask(String mask){
        return Optional.ofNullable(mask).filter(s -> !s.isEmpty()&&NET_MASK.containsValue(mask))
                .orElseThrow(() -> new RuntimeException( mask + "掩码不合法."));
    }
    public static class IpInf{
        /** ip */
        private final Inf ip;
        /** 掩码 */
        private final Inf mask;
        /** 网段 */
        private final Inf segment;
        /** 广播地址 */
        private final Inf broadcast;
        /** 开始ip */
        private final Inf startIp;
        /** 结束ip */
        private final Inf endIp;
        /** 可用ip数 */
        private final Long count;
        /**
         * 初始化
         * @param ip 如 192.168.1.1
         * @param mask 掩码 如 255.255.255.255
         */
        public IpInf(String ip,String mask){
            System.out.println("ip:"+ip+",mask:"+mask);
            this.ip = new Inf(checkIp(ip));
            this.mask = new Inf(checkMask(mask));
            //网段 = ip & 掩码
            this.segment = new Inf(this.ip.val & this.mask.val);
            // 广播地址 网段末尾用1补齐
            this.broadcast = new Inf(this.segment.val | (~this.mask.val & VALIDATE_DATA));
            // 开始地址 网段+1
            this.startIp = new Inf(this.segment.val + 1L);
            // 结束地址 广播地址-1
            this.endIp = new Inf(this.broadcast.val - 1L);
            this.count = this.endIp.val - this.startIp.val;
        }

        public Inf ip() { return ip; }
        public Inf mask() { return mask; }
        public Inf segment() { return segment; }
        public Inf broadcast() { return broadcast; }
        public Inf startIp() { return startIp; }
        public Inf endIp() { return endIp; }
        public Long count() { return count; }

        @Override
        public String toString() {
            return "{ip=" + ip + ", mask=" + mask + ", segment=" + segment + ", broadcast=" + broadcast
                    + ", startIp=" + startIp + ", endIp=" + endIp + ", count=" + count + '}';
        }
    }
    public static class Inf{
        private final String lab;
        private final Long val;
        Inf(String l){ this.lab = l;this.val = ip2Long(l); }
        Inf(Long v){ this.val = v;this.lab = long2ip(v); }
        public Long toLong() { return val; }
        public String toStr() { return lab; }

        @Override
        public String toString() {
            return "{str='" + lab + "', long=" + val + '}';
        }
    }
}



测试

本机ip:192.168.***.171
-------------
ip:192.168.1.2,mask:255.255.254.0
{ip={str='192.168.1.2', long=3232235778}, mask={str='255.255.254.0', long=4294966784}, segment={str='192.168.0.0', long=3232235520}, broadcast={str='192.168.1.255', long=3232236031}, startIp={str='192.168.0.1', long=3232235521}, endIp={str='192.168.1.254', long=3232236030}, count=509}
ip:192.168.1.3,mask:255.255.255.0
{ip={str='192.168.1.3', long=3232235779}, mask={str='255.255.255.0', long=4294967040}, segment={str='192.168.1.0', long=3232235776}, broadcast={str='192.168.1.255', long=3232236031}, startIp={str='192.168.1.1', long=3232235777}, endIp={str='192.168.1.254', long=3232236030}, count=253}
-------------
ip:10.10.10.116>>>168430196
ip:10.10.10.116,startIP:10.10.1.0,endIP:10.10.255.255,>>>true
-------------
ip:10.2.1.0,cip:10.2.0.0/17,>>>true

截图

在这里插入图片描述



END

代码仅供参考,请充分测试后在使用。谢谢Thanks♪(・ω・)ノ



版权声明:本文为privateobject原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。