我对 Guava 的InetAddress.coerceToInteger方法有疑问。
根据文档的方法:
公共静态 int coerceToInteger(InetAddress ip)
'无论提供的参数是否为 IPv4 地址,都返回一个表示 IPv4 地址的整数。'
但是,IPv4 范围是无符号的 32 位,而 Java 的 int 是有符号的 - 意味着返回的值只能覆盖 IPv4 相关范围的一半。
我错过了某人还是该方法存在真正的问题?
谢谢
我对 Guava 的InetAddress.coerceToInteger方法有疑问。
根据文档的方法:
公共静态 int coerceToInteger(InetAddress ip)
'无论提供的参数是否为 IPv4 地址,都返回一个表示 IPv4 地址的整数。'
但是,IPv4 范围是无符号的 32 位,而 Java 的 int 是有符号的 - 意味着返回的值只能覆盖 IPv4 相关范围的一半。
我错过了某人还是该方法存在真正的问题?
谢谢
32 位值是 32 位值,无论是有符号还是无符号,它都可以有 2^32 个值。如果您有一个像 192.168.0.1 这样的地址,它将是一个负数,不会丢失任何信息。如果将其转换为字节(也有符号),则不会丢失任何信息。
顺便说一句:对于 IPv4 地址,您可以使用此技巧
int address = ip.hashCode();
要将 32 位有符号值视为 32 位无符号值,您可以
int address32 = ...
long address = address32 & 0xFFFFFFFFL;
但是,在大多数情况下,您不需要这样做。
我认为 Javadoc 包含答案:
IPv6 地址在转换为整数之前被强制转换为 IPv4 地址。
只要有应用程序假定所有 IP 地址都是 IPv4 地址,因此可以安全地转换为整数(无论出于何种目的),此函数也可用于处理 IPv6 地址,直到应用程序得到适当修复。
注意:强制转换为 IPv4 地址的 IPv6 地址只能用于基本识别或索引到真实 InetAddresses 集合的目的。它们不能用作网络通信的真实地址。
换句话说,如果您提供 IPv6 地址,不要期望它是实际可用的地址。准备好在您的代码或网络中处理具有特殊条件的强制地址。在我看来,文档可以从一个例子中受益匪浅。
Java 中的 long 是 64 位值,IPv4 地址只有 32 位值。挑战在于 Java 没有无符号数据类型,因此需要一些魔法来读取无符号值,通常是通过上转换为长整数。番石榴也涵盖了这一点:
InetAddress addr = InetAddress.getLocalHost();
long ip = UnsignedInts.toLong (InetAddresses.coerceToInteger (addr));