判断某个IP是公共IP还是保留IP

工作中遇到一个需求, 需要判断所给IP是否是公共IP, 而不是保留IP. 本以为所谓的保留IP也就是 几类ip中的一段IP段:

A类 10.0.0.0–10.255.255.255
B类 172.16.0.0–172.31.255.255
C类192.168.0.0–192.168.255.255

网上大多也是这么写的. 但深究之下, 发现远没有这么简单, 下面是我搜集的所有保留ip段:

0.0.0.0/8,
10.0.0.0/8,
100.64.0.0/10,
127.0.0.0/8,
169.254.0.0/16,
172.16.0.0/12,
192.0.0.0/24,
192.0.2.0/24,
192.88.99.0/24,
192.168.0.0/16,
198.18.0.0/15,
198.51.100.0/24,
203.0.113.0/24,
224.0.0.0/4,
240.0.0.0/4,
255.255.255.255/32

斜杠后是子网掩码, 想要看具体的IP区间, 可以访问这个网址: IP 地址在线计算器

基于此, 写了一段判断是否为公共ip的程序. 大概思路是将ip转换为long型值 进行按位与, 结果如果等于其对应的子网掩码, 则可判定为这是一个保留IP. 这种计算方法比用正则表达式是快很多的, 而且, 上述ip的正则也很不好写.

代码中用到了我在scala很喜欢的tuple类型, 需要引入这个第三方jar包:

        <dependency>
            <groupId>org.javatuples</groupId>
            <artifactId>javatuples</artifactId>
            <version>1.2</version>
            <scope>compile</scope>
        </dependency>

代码如下:

import org.javatuples.Pair;

import java.util.Arrays;
import java.util.List;


// 参考
// http://jingyan.baidu.com/article/4f7d57128ea05f1a201927d6.html
// http://blog.csdn.net/chang_mu/article/details/53031961

public class IPUtils {
    private static final int IPV4_PART_COUNT = 4;

// 新来的ip与子网掩码做与运算, 结果若在reserveIps中, 那就是保留ip
//"0.0.0.0/8","10.0.0.0/8","100.64.0.0/10","127.0.0.0/8","169.254.0.0/16","172.16.0.0/12","192.0.0.0/24","192.0.2.0/24","192.88.99.0/24",
// "192.168.0.0/16","198.18.0.0/15","198.51.100.0/24","203.0.113.0/24","224.0.0.0/4","240.0.0.0/4","255.255.255.255/32"
// 转为数字
// private static final List<Long> reserveIps = Arrays.asList(0L,167772160L,1681915904L,2130706432L,2851995648L,2886729728L,3221225472L,
// 3221225984L,3227017984L,3232235520L,3323068416L,3325256704L,3405803776L,3758096384L,4026531840L,4294967295L);

// 掩码  "240.0.0.0"/4,"255.0.0.0"/8,"255.192.0.0"/10,"255.240.0.0"/12,"255.254.0.0"/15,"255.255.0.0"/16,"255.255.255.0"/24,"255.255.255.255"/32
// 转为数字
// private static final List<Long> maskIps = Arrays.asList(4026531840L,4278190080L,4290772992L,4293918720L,4294836224L,4294901760L,4294967040L,4294967295L);

    // 对偶: (掩码, 网络号)
    private static final List<Pair<Long, Long>> reserveIps = Arrays.asList(
            Pair.with(4026531840L, 3758096384L), //  224.0.0.0/4  -- 240.0.0.0
            Pair.with(4026531840L, 4026531840L), //  240.0.0.0/4  -- 240.0.0.0

            Pair.with(4278190080L, 0L),          //  0.0.0.0/8  -- 255.0.0.0
            Pair.with(4278190080L, 167772160L),  //  10.0.0.0/8 --255.0.0.0
            Pair.with(4278190080L, 2130706432L), //  127.0.0.0/8 --255.0.0.0

            Pair.with(4290772992L, 1681915904L), //  100.64.0.0/10 --255.192.0.0

            Pair.with(4293918720L, 2886729728L), // 172.16.0.0/12 -- 255.240.0.0

            Pair.with(4294836224L, 3323068416L), // 198.18.0.0/15, --255.254.0.0

            Pair.with(4294901760L, 2851995648L), // 169.254.0.0/16 --255.255.0.0
            Pair.with(4294901760L, 3232235520L), // 192.168.0.0/16 --255.255.0.0

            Pair.with(4294967040L, 3221225472L), //192.0.0.0/24,
            Pair.with(4294967040L, 3221225984L), //192.0.2.0/24,
            Pair.with(4294967040L, 3227017984L), //192.88.99.0/24,
            Pair.with(4294967040L, 3325256704L), //198.51.100.0/24
            Pair.with(4294967040L, 3405803776L), //203.0.113.0/24,

            Pair.with(4294967295L, 4294967295L) //255.255.255.255/32
    );

    // 将 ip 转为 数字
    private static long ip2Long(String ipAddress) {
        long result = 0;
        String[] ipAddressInArray = ipAddress.split("\\.");
        if (ipAddressInArray.length != 4) return -1;

        try {
            for (int i = 3; i >= 0; i--) {
                long ip = Long.parseLong(ipAddressInArray[3 - i]);
                //left shifting 24,16,8,0 and bitwise OR
                result |= ip << (i * 8);
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }

    }

    public static boolean isPublicIP(String ipStr) {
        long ip_numerical = ip2Long(ipStr);
        if (ip_numerical == -1) return false;

        for (Pair<Long, Long> reserveIp : reserveIps) {
            long result = reserveIp.getValue0() & ip_numerical;
            if (result == reserveIp.getValue1())
                return false;
        }
        return true;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值