用于数据库存储的 IP 压缩

发布于 2024-10-27 08:09:41 字数 212 浏览 11 评论 0原文

我有一个数据库,存储所有使用过某个功能的用户的 IP 号(即:在民意调查中投票),我想避免同一用户或 IP 投票两次。

因此,我一直存储在我的民意调查中投票的匿名用户的所有 IP。我的数据库充满了像 123.456.789 这样的 IP...

但是,效率很低,是否有一种单向函数可以将 IP 压缩为较短的字符串?

比如 123.456.798 => %dA

I have a database that stores the IP number of all users that have used a feature (ie: voted on a poll), and I want to avoid the same user or IP from voting twice.

As a result I have been storing all the IPs of the anonymous users that have voted on my polls. My database is filled with IPs like 123.456.789...

However, that is inefficient, is there a one way function that compresses and IP into a shorter string?

like 123.456.798 => %dA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

↙温凉少女 2024-11-03 08:09:41

对于 IPv4,您可以将 IP 地址压缩为 int,如下所示:

Scanner scanner = new Scanner(ip).useDelimiter("\\.");
int value = (scanner.nextInt() << 24) | (scanner.nextInt() << 16)
        | (scanner.nextInt() << 8) | scanner.nextInt();

这也可以颠倒过来:

String ip = ((value >> 24) & 0xFF) + "." + ((value >> 16) & 0xFF)
        + "." + ((value >> 8) & 0xFF) + "." + (value & 0xFF);

For IPv4 you can compress an IP address into an int like this:

Scanner scanner = new Scanner(ip).useDelimiter("\\.");
int value = (scanner.nextInt() << 24) | (scanner.nextInt() << 16)
        | (scanner.nextInt() << 8) | scanner.nextInt();

This can be reversed too:

String ip = ((value >> 24) & 0xFF) + "." + ((value >> 16) & 0xFF)
        + "." + ((value >> 8) & 0xFF) + "." + (value & 0xFF);
欢烬 2024-11-03 08:09:41

如果您将它们作为字符串存储在数据库中,是的,这将是浪费的。您可以在存储它们之前将它们转换为 4 字节整数。

java.net.InetAddress 类有一个 getByName 方法,该方法将返回一个新的 InetAddress 对象。对返回的对象调用 getAddress 会获取地址的字节数组,您可以轻松地将其转换为 int 。

请注意,InetAddress 也适用于 IPv6 地址,因此您需要确保可以将这些地址存储在数据库中,或者检查从 getByName 调用返回的 InetAddress 类型以确保它是 IPv4 地址。

If you're storing them as strings in your database, yes that's going to be wasteful. You can convert them into 4 byte integers before you store them.

The class java.net.InetAddress has a getByName method that will return a new InetAddress object. Calling getAddress on the returned object gets you a byte array of the address, which you can turn into an int easily enough.

Note that InetAddress will also work with IPv6 addresses, so you'll want to either make sure you can store those in your DB, or check the type of InetAddress returned from the getByName call to make sure it's an IPv4 address.

虫児飞 2024-11-03 08:09:41

IPv4 地址是 32 位。在点分符号中,您有一个最多 15 个字节的字符串,但仍然表示 32 位(4 字节)地址。显而易见的步骤是将它们转换为二进制格式,例如使用 inet_atoninet_pton。通常建议新代码使用后者,因为它除了处理 IPv4 之外还处理 IPv6 地址。

如果您需要超越这个范围,您可以尝试将地址存储在字典树中。但这不太适合您的正常数据库模型,因此除非您确实有很多或匿名用户,否则可能不会可能不值得这么麻烦。

An IPv4 address is 32 bits. In dotted notation you have a string of up to 15 bytes that still represents a 32-bit (4-byte) address. The obvious step would be to convert them to binary format, such as with inet_aton or inet_pton. The latter is generally recommended for new code, since it handles IPv6 addresses in addition to IPv4.

If you need to go beyond that, you might try storing the addresses in a trie. That doesn't fit your normal database model very well though, so unless you really have a lot or anonymous users, it may not be probably isn't worth the trouble.

枯寂 2024-11-03 08:09:41

假设您不支持 IPv6,则 IP 地址适合 int。你真的需要更小的东西吗?

如果您支持 IPv6,则两个长整型就可以了。看起来还是很小。

Assuming you aren't supporting IPv6, an ip address fits in an int. You really need something smaller?

And if you are supporting IPv6, two longs will do. Still seems pretty small.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文