将地址映射到唯一编号

时间:2016-06-10 19:13:52

标签: java algorithm hash ip-address ipv4

从IP地址创建唯一号码的最佳方法是什么?

19.22.145.103

我计划将每个八位字节相加以得到唯一的数字,但看起来我可能没有为每个IP地址获取唯一的数字。

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

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

  • 首先,通过将其存储为32位数据类型来获取唯一编号的最佳方法是什么?
  • 其次现在问题是我需要在short数据类型中存储此唯一编号。由于short是16位,因此我们可能无法将IPv4映射为唯一的short。如果我们仍然使用short数据类型而不是像我上面使用的那样使用每个八位字节的总和,还有其他方法我们可以提出更少的冲突吗?

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

3 个答案:

答案 0 :(得分:1)

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();
}

这为您提供了2 32 可能的值。如果你想将它映射到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))
}

您可以添加像

这样的aggetate函数
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));
}

答案 1 :(得分:0)

您的任务通常不可能。所以我会从业务领域寻找快捷方式。

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

答案 2 :(得分:-1)

我有一种新的方式..查看代码,它可以保证您的代码将是独一无二的......

@model IEnumerable<WebApplication1.Models.EmployeeProject>
....
<table class="table">
    <tr>
        <th>@Html.DisplayNameFor(model => model.EmployeeName)</th>
        <th>@Html.DisplayNameFor(model => model.ProjectName)</th>
        ....        
    </tr>
    @foreach (var item in Model)
    {
        using (Html.BeginForm("Edit","EmployeeProject",item))
        {
            @Html.AntiForgeryToken()
            <tr>
                @Html.ValidationSummary(true)
                @Html.HiddenFor(model => item.EmployeeProjectID)
                @Html.HiddenFor(model => item.EmployeeID)
                @Html.HiddenFor(model => item.ProjectID)
                <td>
                    @Html.DisplayFor(model => item.EmployeeName)
                    @Html.ValidationMessageFor(model => item.EmployeeName)
                </td>
                <td>
                    @Html.DisplayFor(model => item.ProjectName)
                    @Html.ValidationMessageFor(model => item.ProjectName)
                </td>
                ....
                <td class="form-group">
                    <td class="col-md-offset-0 col-md-5">
                        <input type="submit" value="Save" />
                    </td>
                </td>
            </tr>
        }
    }
</table>