从 127.0.0.1 到 2130706433,然后再返回
Posted
技术标签:
【中文标题】从 127.0.0.1 到 2130706433,然后再返回【英文标题】:Going from 127.0.0.1 to 2130706433, and back again 【发布时间】:2011-01-15 12:31:16 【问题描述】:使用标准 Java 库,从 IPV4 地址的点分字符串表示 ("127.0.0.1"
) 到等效整数表示 (2130706433
) 的最快方法是什么。
相应地,反转上述操作的最快方法是什么 - 从整数2130706433
到字符串表示"127.0.0.1"
?
【问题讨论】:
【参考方案1】:您也可以使用Google Guava InetAddress 类
String ip = "192.168.0.1";
InetAddress addr = InetAddresses.forString(ip);
// Convert to int
int address = InetAddresses.coerceToInteger(addr);
// Back to str
String addressStr = InetAddresses.fromInteger(address));
【讨论】:
我认为这是最简单的。除非您关心微秒级性能,否则请使用处理所有字节序和符号的标准库【参考方案2】:使用the IPAddress Java library 很简单,每个方向一行代码。 免责声明:我是该库的项目经理。
IPv4Address loopback = new IPAddressString("127.0.0.1").getAddress().toIPv4();
System.out.println(loopback.intValue());
IPv4Address backAgain = new IPv4Address(loopback.intValue());
System.out.println(backAgain);
输出:
2130706433
127.0.0.1
【讨论】:
【参考方案3】:另一种方式:
public static long ipToLong(String ipAddress)
String[] ipAddressInArray = ipAddress.split("\\.");
long result = 0;
for (int i = 0; i < ipAddressInArray.length; i++)
int power = 3 - i;
int ip = Integer.parseInt(ipAddressInArray[i]);
result += ip * Math.pow(256, power);
return result;
【讨论】:
【参考方案4】:字符串转整数:
int pack(byte[] bytes)
int val = 0;
for (int i = 0; i < bytes.length; i++)
val <<= 8;
val |= bytes[i] & 0xff;
return val;
pack(InetAddress.getByName(dottedString).getAddress());
整数转字符串:
byte[] unpack(int bytes)
return new byte[]
(byte)((bytes >>> 24) & 0xff),
(byte)((bytes >>> 16) & 0xff),
(byte)((bytes >>> 8) & 0xff),
(byte)((bytes ) & 0xff)
;
InetAddress.getByAddress(unpack(packedBytes)).getHostAddress()
【讨论】:
127.0.0.1 给出 2130706433,但 255.255.255.255 没有给出 4294967295。签名与未签名的问题? 以无符号形式打印,将结果转换为 long 并屏蔽高位:((long)packedBytes)&0xffffffff
字节在Java中最多为2^7-1,这样每个字节将无法显示任何大于127的整数。正确的做法是使用int来存储数字。跨度>
【参考方案5】:
如果您需要学习长手数学,您可以使用 Substr 删除八位字节。 将表示类的第一个八位字节乘以 (256*256*256) 或 (2^24) 秒乘以 (256*256) (2^16) 第三乘以 (256) (2^8) 第四乘以 1 或 (2^0)
127 * (2^24) + 0 *(2^16) + 0 * (2^8) + 1 * (2^0) 2130706432 + 0 + 0 + 1 = 2130706433
【讨论】:
【参考方案6】:我修改了我原来的答案。在 Sun 的 InetAddress
实现中,hashCode
方法生成 IPv4 地址的整数表示,但正如评论者正确指出的那样,JavaDoc 不能保证这一点。因此,我决定改用ByteBuffer
类来计算IPv4地址的值。
import java.net.InetAddress;
import java.nio.ByteBuffer;
// ...
try
// Convert from integer to an IPv4 address
InetAddress foo = InetAddress.getByName("2130706433");
String address = foo.getHostAddress();
System.out.println(address);
// Convert from an IPv4 address to an integer
InetAddress bar = InetAddress.getByName("127.0.0.1");
int value = ByteBuffer.wrap(bar.getAddress()).getInt();
System.out.println(value);
catch (Exception e)
e.printStackTrace();
输出将是:
127.0.0.1
2130706433
【讨论】:
hashCode() 是否明确定义为进行 4 字节到 int 的转换?如果不是,我怀疑是这样。请注意,解释总是好的。 IP地址到int的映射需要双射。 hashCode 不保证这一点。 这应该被否决。 Javadocs 中没有任何内容可以保证这种行为,它恰好是目前(明智的)Sun 实现。 Sun 可以将其更改为仅返回一个常量,它仍然可以正常运行,但您的示例会失败。 您是正确的,InetAddress 的 hashCode() 方法没有指定如何计算散列。我将把答案留在这里,因为它使用 InetAddress 的标准实现“工作”。 我已根据您的担忧更新了我的答案。我的示例现在使用 ByteBuffer 类来计算 IPv4 地址的整数值,而不是依赖 InetAddress 的 hashCode 方法。【参考方案7】:我没试过。性能,但最简单的方法可能是使用 NIO ByteBuffer。
例如
byteBuffer.put(integer).array();
会返回一个表示整数的字节数组。您可能需要修改字节顺序。
【讨论】:
为什么不直接选择一个字节顺序并使其成为 ByteBuffer 的字节顺序?这样您就不必担心不同机器上的不同默认字节顺序。编辑:没关系,默认是大端。以上是关于从 127.0.0.1 到 2130706433,然后再返回的主要内容,如果未能解决你的问题,请参考以下文章
如何修复 Magento-1.9.4 中的“无法将 VCL 应用到 127.0.0.1:6082:无法从 Varnish 读取响应代码”错误
保存Ajax但不将CORS cookie从127.0.0.1发送到服务
如何强制 where 子句中的函数在 oracle 中执行一次?