ip存储
IP 地址存储方案:IPv4 与 IPv6 的高效处理方式
在开发中,IP 地址(尤其是用户访问日志、设备管理场景)需要高效存储和查询。直接存储字符串形式的 IP 不仅占用空间大,还不利于范围查询(如判断某个 IP 是否在指定网段内)。本文将详细讲解 IPv4 和 IPv6 地址的数字化存储方案,包括转换原理、代码实现及应用场景。
IPv4 地址的存储:使用 long 类型
IPv4 地址由 4 个 0-255 的整数组成(如 192.168.1.1),总长度为 32 位(4×8 位),刚好可以用一个 64 位的 long 类型存储。
转换原理
将 IPv4 地址的 4 个分段视为 32 位二进制数的 4 个字节,按从左到右的顺序拼接后转换为十进制整数。例如:
- IP 地址
192.168.1.1可拆分为192、168、1、1; - 转换为二进制:
11000000.10101000.00000001.00000001; - 拼接后为 32 位二进制数,转换为十进制即
3232235777。
代码实现
public class IPv4Converter {
/**
* 将 IPv4 字符串转换为 long 类型
* @param ipString IPv4 地址(如 "192.168.1.1")
* @return 对应的 long 值,转换失败返回 -1
*/
public static long ipToLong(String ipString) {
// 拆分 IP 地址为 4 个分段
String[] segments = ipString.split("\\.");
if (segments.length != 4) {
return -1; // 格式错误
}
long result = 0;
try {
// 每个分段左移相应位数后累加(第一段占最高 8 位,第四段占最低 8 位)
result += Long.parseLong(segments[0]) << 24; // 第一段:左移 24 位
result += Long.parseLong(segments[1]) << 16; // 第二段:左移 16 位
result += Long.parseLong(segments[2]) << 8; // 第三段:左移 8 位
result += Long.parseLong(segments[3]); // 第四段:不左移
return result;
} catch (NumberFormatException e) {
return -1; // 分段包含非数字
}
}
/**
* 将 long 类型转换为 IPv4 字符串
* @param ipLong 用 long 存储的 IPv4 地址
* @return 对应的 IPv4 字符串
*/
public static String longToIp(long ipLong) {
// 从 long 中提取 4 个分段(通过右移和与运算)
StringBuilder ip = new StringBuilder();
ip.append((ipLong >>> 24)).append("."); // 提取最高 8 位
ip.append((ipLong >>> 16) & 0xFF).append("."); // 提取次高 8 位(&0xFF 确保只取 8 位)
ip.append((ipLong >>> 8) & 0xFF).append("."); // 提取次低 8 位
ip.append(ipLong & 0xFF); // 提取最低 8 位
return ip.toString();
}
// 测试
public static void main(String[] args) {
String ip = "255.255.255.255";
long ipLong = ipToLong(ip);
System.out.println(ipLong); // 输出:4294967295
System.out.println(longToIp(ipLong)); // 输出:255.255.255.255
}
}