MySQL的IP地址与数字互转原理

1、inet_aton与inet_ntoa

inet_aton是把ip地址转为数字的函数,记忆小技巧,inet表示网络相关,在c语言中a习惯性表明字符串,to就是转换的,n表明数字,aton就是字符串转数字,同理inet_ntoa是把数字转换为字符串IP。java

SELECT inet_aton('192.168.0.1') as ip2num,inet_ntoa(3232235521) as num2ip FROM DUAL;

ip数字互转

2、算法

假设IP地址为:a.b.c.d算法

那么对应的num为:sql

a * 256^3 + b * 256^2 + c * 256^1 + d * 256^0
# 等价于
a * 2^24 + b * 2^16 + c * 2^8 + d

为何这么转换呢?网络

由于ip地址原本就是4字节,每个字节最大值就是255,因此彻底可使用一个4字节的无符号整型来存放。函数

2的幂运算就至关于移位运算,因此2^24就至关于向左移了24位,a一个字节最大11111111, 移位运算以后:code

11111111 00000000 00000000 00000000

同理,其余位也同样。orm

注意:必须是无符号整型,由于有符合的整型除了最高位符号位,只有31位,放不下blog

这样也方便还原,从数字到ip取对应字节转换为数字就能够了。ip

3、ip到数字实现

public static long ipToNum(String ip) {
    String[] parts = ip.split("\\.");
    assert parts.length == 4;
    Long num = 0L;
    for(int i=0;i<parts.length;i++){
        num += (Long.parseLong(parts[i]) << (24 - i * 8));
    }
    return num;
}

java由于没有无符号整型,因此使用long,下面给一个更加直观的实现。字符串

public static long ipToNum(String ip) {
    String[] parts = ip.split("\\.");
    assert parts.length == 4;
    return (Long.parseLong(parts[0]) << 24) + (Long.parseLong(parts[1]) << 16) + (Long.parseLong(parts[2]) << 8) + Long.parseLong(parts[3]);
}

4、数字到ip实现

public static String numToIP(long ipNum){
    String result = String.format("%d.%d.%d.%d", ipNum >>> 24, (ipNum & 0x00FFFFFF) >>> 16, (ipNum & 0x0000FFFF) >>> 8, ipNum & 0x000000FF);
    return result;
}

数字到ip须要注意的是,须要清除高位,由于低位在移位以后已经被丢弃了,因此不须要清除。

清除位利用的技巧是&运算中0与任何位进行&都为0。

相关文章
相关标签/搜索