IP地址与int或者long类型互转(Java、PHP)

来源:互联网 发布:重庆数据分析的项目 编辑:程序博客网 时间:2024/06/06 11:37

对数据库了解的同学都知道数字类型其实是要比字符串类型的column在处理上速度快很多的,所以为了存储和查询速度考虑,我们通常把IP地址转为数字来存储,通常用int存储,但是要注意要使用unsigned ,不然128以上的就无法存储了。

原理

那我们究竟如何存储IP地址呢?

  • 我们知道IP地址(ipv4)分为四段,每一段的范围是0-255,而这个范围恰好可以用8bit的二进制来表示,因为2的8次方为256,从0到255正好为256个数字。
  • 所以,实际上我们可以用类似xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx 的形式来表示一个ipv4的地址,其中x 为0或1。
  • 然后,我们把中间的点去掉,就是一个32bit的二进制数字了,恰好是一个int类型(数据库中占32bit)所能表示的范围。
  • 因此,我们只需要将IP每一段都用二进制表示,再拼到一起,就可以表示一个IP地址了。

如何拼装

  • 10.1.8.12 为例,四段分别是101812,用8bit的二进制表示分别为00001010000000010000100000001100,其中不足8位的数字用0在左边补齐。
  • 最后我们要的结果其实是00001010000000010000100000001100,也就是按照顺序,拼接起来,转为十进制位167839756(我口算的,你们信不;-))。
  • 我们依次从左到右这四段,分别左移24位、16位、8位、0位,Java中位用逻辑左移运算符<< ,然后我们可以得到00001010000000000000000000000000000000010000000000000000 , 0000110000000000, 00001100
  • 最后我们将这几段二进制数做或操作,Java中逻辑或运算符为| (有一个为1则此位为1)于是我们就可以得到00001010000000010000100000001100 , 十进制就是167839756.

如何还原

  • 明白了如何拼装的之后,我们还原就很容易了
  • 我们把这个长长的数字右移,分别把00001010000000010000100000001100 右移24位、16位、8位、0位,然后得到00001010000010100000000100001010000000010000100000001010000000010000100000001100
  • 然后,我们用11111111 也就是 0xFF 来跟上述的四段数字以此做与操作,java中运算符位& (同1为1,有一个为0则此位为0), 我们就可以得到00001010000000010000100000001100,十进制依次为:101812,最后中间加点,就还原了。
  • 这个与操作实际上就是起到了截断的作用,只取8位,因为0xFF 只有8位,其左边可以用任意多的0填充,例如0xFF 跟 例子IP中的第三段做与操作:000000000000000011111111 & 000010100000000100001000,根据与运算的规则,高于8位的都是跟0与,所以得到的也全是0,真正有效的低8位。
  • 事实上,开头的10 ,我们完全可以不用与操作,因为右移24位后,就剩下8位,就是我们要的。

代码实现

Java

package com.vien.ip;/** * @author Vien * @date 2017/11/17 */public class IPUtils {    /**     * convert ip to long     *     * @param ip the string of ip address     * @return long of ip     */    public static long ip2long(String ip) {        System.out.println(ip);        String[] slice = ip.split("\\.");        return (Long.valueOf(slice[0]) << 24) | (Long.valueOf(slice[1]) << 16) | (Long.valueOf(slice[2]) << 8) | Long.valueOf(slice[3]);    }    /**     * convert long to ip     *     * @param ip long     * @return string of ip     */    public static String long2ip(long ip) {        StringBuilder ipStr = new StringBuilder();        ipStr.append((ip >>> 24)).append(".");        ipStr.append((ip >>> 16) & 0xFF).append(".");        ipStr.append((ip >>> 8) & 0xFF).append(".");        ipStr.append(ip & 0xFF);        return ipStr.toString();    }    public static void main(String[] args) {        System.out.println(ip2long("10.1.8.12"));        System.out.println(long2ip(167839756));    }}

PHP

其实PHP提供了相关函数ip2long() 将 IP转为longlong2ip()long还原为IP

MySQL

MySQL也提供相关函数,可以用于查询,例如:mysql> select inet_aton('10.1.8.12');+------------------------+| inet_aton('10.1.8.12') |+------------------------+|              167839756 |+------------------------+1 row in set (0.01 sec)mysql> select inet_ntoa(167839756);+----------------------+| inet_ntoa(167839756) |+----------------------+| 10.1.8.12            |+----------------------+1 row in set (0.00 sec)

更多:vien.我爱你

原创粉丝点击