将地址映射到唯一编号

Mapping Address to unique number

从 IP 地址生成唯一编号的最佳方法是什么?

19.22.145.103

我正计划对每个八位字节求和以获得唯一编号,但看起来我可能无法为每个 IP 地址获得唯一编号。

Sum of each octet 19 + 22 + 145 + 103 = 289 as the unique number.

我已经知道我们无法将 IPv4 映射到 16 位,因此可以接受冲突较少的解决方案。我正在寻找以下两点提到的解决方案。

我所有的 IP 地址都以 10. 开头,如果有助于确定算法,那么冲突就会减少。

https://en.wikipedia.org/wiki/Hash_function

制作散列函数,然后将其切割成的大小。例如:

(or some other prime numbers) ( 7 ^ 19 + 5 * 22 + 11 * 145 + 17 * 103 ) % size_of_short

你的任务通常是不可能的。所以我会从业务领域寻找捷径。

您需要映射所有个IP地址吗?您可以跳过 127.*.*.*192.168.*.*。但这还不够。你需要减少到 16 位,这是一个完整范围的摩擦:1 / 2^16 ~ 1 / 64000

IPv4 是 4 个八位字节,因此您可以使用类似

的方式获得唯一的映射
public static int asInt(byte[] addr) {
    return (addr[0] & 0xFF) | ((addr[1] & 0xFF) << 8)
          | ((addr[2] & 0xFF) << 16) | ((addr[3] & 0xFF) << 24);
}

public static int asInt(byte[] addr) {
    return ByteBuffer.wrap(addr).readInt();
}

这为您提供了 232 个可能的值。如果您想将其映射到 16 位并确保它是唯一的,您需要将映射存储在其他地方,例如

final Map<Integer, Short> mapping = new ConcurrentHashMap<>();
int next = 0;

public short idFor(byte[] bytes) {
    Integer i = asInt(bytes);
    return mapping.computeIfAbsent(i, x -> next++);
}

在 Java 7 你可以做

public short idFor(byte[] bytes) {
    Integer i = asInt(bytes);
    synchronized(mapping) {
        Short s = mapping.get(i);
        if (s == null)
            mapping.put(i, s = next++);
        return s;
    }
}

注意,一个 16 位值只能有 65536 个可能的唯一值。

如果你想要一个简单的散列,你可以使用像

这样的东西
public short hash(int n) {
    return (short) (n ^ (n >>> 16))
}

您可以添加聚合函数,例如

public short hash(int n) {
    n *= 10191; // an odd prime of around 2^^16
    return (short) (n ^ (n >>> 16))
}

不理想的是最高位不会以这种方式产生太多随机性。您可以改用 64 位计算。

public short hash(int n) {
    long n2 = n * 0x6d0f27bdL; 
    n2 ^= (n2 >>> 21) ^ (n2 >>> 42);
    return (short) (n ^ (n >>> 16) ^ (n >> 32));
}

我有一个新方法..检查代码,它保证您的代码是唯一的...

private static final int HASH_PRIME = 23;
public static short convertIP(String ip) {
    String res = "";
    for(String num: ip.split("\.")) {
        int val = Integer.parseInt(num);
        while(val>HASH_PRIME) {
            val = val / HASH_PRIME;
        }
        if(new Random().nextInt(10) <= 4) {
            res += convertChar(val);
        } else {
            res += val;
        }
    }
    System.out.println("result = "+res); // the result could be anything like: T2264, 19WGE, TWGE, 1922G4, etc

    return (short) (res.hashCode() % Short.MAX_VALUE);
}

private static char convertChar(int num) {
    return (char)((num % 26) + 65);
}

public static void main(String[] args) {
    System.out.println(convertIP("19.22.145.103"));
    // the short code for the same IP will be unique majorly.. i.e. 24311, 23784, 31968, 16079, 23767 .. etc
}