IP 地址与 Long 互转之 IPUtil 详解

分享 苏牛 ⋅ 于 2020-07-24 20:37:53 ⋅ 4687 阅读

概述
IP地址一般是一个32位的二进制数。
意思就是如果将IP地址转换成二进制表示应该有32为那么长,但是它通常被分割为4个“8位二进制数”(也就是4个字节,每个代表的就是小于2的8次方)。
IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之间的十进制整数。
例:点分十进IP地址(100.4.5.6),实际上是32位二进制数(01100100.00000100.00000101.00000110)
IPUtils 就是利用了这个特性进行 IP地址转换的。
IP转Long原理
首先我们先看一下 IP地址转Long的方法

    public static long ip2long(String ip) {
        String[] fields = ip.split("\\.");
        if (fields.length != 4) {
            return 0L;
        }

        long r = Long.parseLong(fields[0]) << 24; // 获取高8位
        r |= Long.parseLong(fields[1]) << 16;   // 获取中8位
        r |= Long.parseLong(fields[2]) << 8;    // 获取中8位
        r |= Long.parseLong(fields[3]);         // 获取低8位

        return r;
    }

举例说明:假如说传入IP地址为 114.249.229.255。通过 . 分隔符分割之后形成 “fields” 的四个元素 ["114","249","229","255"],切分好之后这四个元素分别做位运算操作
第一个元素 114  二进制是  01110010 向左移动24位 01110010 00000000 000000000 00000000
第二个元素 249  二进制是  11111001 向左移动16位 00000000 11111001  00000000   00000000
第三个元素 229 二进制是   11100101 向左移动8位   00000000 00000000 11100101   00000000
第四个元素 255  二进制是  11111111  不向左移动      0000000  00000000  00000000  11111111
根据算式计算这几个二进制进行 或(|)运算之后的结果
01110010 11111001 11100101 11111111 --> 转换成10进制的 Long 类型 = 1928979967 通过这种算法我们就得到了这个IP的long类型数据
Long转IP原理
首先我们先看一下 Long转IP的方法

    public static String long2ip(long ip) {
        int[] b = new int[4];
        String x = "";
        b[0] = (int) ((ip >> 24) & 0xff);
        b[1] = (int) ((ip >> 16) & 0xff);
        b[2] = (int) ((ip >> 8) & 0xff);
        b[3] = (int) (ip & 0xff);
        x = Integer.toString(b[0]) + "." + Integer.toString(b[1]) + "." + Integer.toString(b[2]) + "."
                + Integer.toString(b[3]);
        return x;
    }

我们将上面得到的数据 1928979967  传入这个方法看我们能得到什么
代码中
  b[0] = (int) ((ip >> 24) & 0xff);
  b[1] = (int) ((ip >> 16) & 0xff);
  b[2] = (int) ((ip >> 8) & 0xff);
  b[3] = (int) (ip & 0xff);
0xff 是十六进制数据 转换为十进制是 255 转换为二进制是 11111111
第一行 b[0] = (int) ((ip >> 24) & 0xff); 首先计算 ip >> 24 向右移动24位之后和 0xff取 与(&)运算是这样算的

  1. ip 转二进制 01110010 11111001 11100101 11111111
  2. ip 向右位移 24位 就变成了 01110010 --> 其实这个位移就是获取高8位上的二进制数据
  3. 将位移好的数据与 255 去 与 运算 01110010 & 11111111 = 01110010 等于 十进制的 114
    通过上面的三步就能完成IP地址的四个位置数据的获取 这样就完成了数据的操作

IP地址判断原理
首先看一下获取地区的方法

    public String getIpArea(String ip){
        long iptemp = IPUtil.ip2long(ip);
        String area = null;
        try{
            Long tempKey = (Long) ipMap.ceilingKey(Long.valueOf(iptemp));
            area = ipMap.get(tempKey);

        }catch(Exception e){
            area = "未知地区";
        }

        return area;

    }

在上面方法中 将传入的IP地址先转换成long类型之后 通过 ipMap 获取这个地址的向上取整的key;
ceilingKey 这个方法就是获取向上取整的key,为啥要这么写呢?
举个例子, 我们刚才的IP地址 114.249.229.255 这个在我们的ip.dat中是这样记录的
114.249.219.0 114.249.229.255 北京市 联通
那么在上面的IP段中 从0到255一共有256个ip,举个例子 114.249.219.115 114.249.219.239 114.249.219.66 都属于这个区间段
那么怎么判断 这256个IP都属于这个区间呢?就是用向上取整的玩法 把上面的IP都转换为long之后 都 大于 114.249.219.0 但是 小于 114.249.229.255,所以此时就可以判定一个范围的IP了!

版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-苏牛,http://hainiubl.com/topics/75236
本帖由 青牛 于 4年前 解除加精
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter