使用 PHP 计算 IPv6 与 IPv4 相比的 IP 地址长格式数字
Calculating IP Address Long Form Number for IPv6 Compared to IPv4 Using PHP
目前我有两种计算IPv4长格式整数的方法:
//IPv4 format: w.x.y.z
$ip_number = (16777216 * $w) + (65536 * $x) + (256 * $y) + $z;
$ip_number = ip2long($ip);
但是如何将 IPv6 计算为长整数?
我正在寻找不需要我安装 PHP.
任何扩展的功能或东西
编辑:
我需要长格式整数,以便我可以比较它以进行 IP 范围查询。以下是 IPv6 范围查询的示例行:
"58569075684585412230123897272863293440","58569076873007849944088961176022548479","MU","Mauritius"
建议:
长存储不是正确的方法。使用,
string inet_ntop ( string $in_addr )
This function converts a 32bit IPv4, or 128bit IPv6 address (if PHP
was built with IPv6 support enabled) into an address family
appropriate string representation.
你也应该看到,
string inet_pton ( string $address )
inet_ntop() 例子
<?php
$packed = chr(127) . chr(0) . chr(0) . chr(1);
$expanded = inet_ntop($packed);
/* Outputs: 127.0.0.1 */
echo $expanded;
$packed = str_repeat(chr(0), 15) . chr(1);
$expanded = inet_ntop($packed);
/* Outputs: ::1 */
echo $expanded;
?>
范围比较
在PHP5.1.0、inet_pton
和inet_pton
中引入了以下两个函数。他们的目的是将人类可读的 IP 地址转换成他们打包的 in_addr
表示。由于结果不是纯二进制,我们需要使用 unpack
函数来应用按位运算符。
这两个函数都支持 IPv6 和 IPv4。唯一的区别是您如何从结果中解压缩地址。对于 IPv6,您将使用 A16 解压内容,对于 IPv4,您将使用 A4 解压。
为了把前面的放在一个透视图中,这里有一个小示例输出来帮助澄清:
// Our Example IP's
$ip4= "10.22.99.129";
$ip6= "fe80:1:2:3:a:bad:1dea:dad";
// ip2long examples
var_dump( ip2long($ip4) ); // int(169239425)
var_dump( ip2long($ip6) ); // bool(false)
// inet_pton examples
var_dump( inet_pton( $ip4 ) ); // string(4)
var_dump( inet_pton( $ip6 ) ); // string(16)
我们在上面证明了 inet_* 系列同时支持 IPv6 和 v4。我们的下一步是将打包结果转换为解包变量。
// Unpacking and Packing
$_u4 = current( unpack( "A4", inet_pton( $ip4 ) ) );
var_dump( inet_ntop( pack( "A4", $_u4 ) ) ); // string(12) "10.22.99.129"
$_u6 = current( unpack( "A16", inet_pton( $ip6 ) ) );
var_dump( inet_ntop( pack( "A16", $_u6 ) ) ); //string(25) "fe80:1:2:3:a:bad:1dea:dad"
注:当前函数returns数组的第一个索引。这相当于说 $array[0].
解包打包后,我们可以看到我们得到了与输入相同的结果。这是一个简单的概念证明,可确保我们不会丢失任何数据。
终于用上了,
if ($ip <= $high_ip && $low_ip <= $ip) {
echo "in range";
}
参考:php.net
好的,这是我最终解决它的方法:
function ipaddress_to_ipnumber($ipaddress) {
$pton = @inet_pton($ipaddress);
if (!$pton) { return false; }
$number = '';
foreach (unpack('C*', $pton) as $byte) {
$number .= str_pad(decbin($byte), 8, '0', STR_PAD_LEFT);
}
return base_convert(ltrim($number, '0'), 2, 10);
}
目前我有两种计算IPv4长格式整数的方法:
//IPv4 format: w.x.y.z
$ip_number = (16777216 * $w) + (65536 * $x) + (256 * $y) + $z;
$ip_number = ip2long($ip);
但是如何将 IPv6 计算为长整数?
我正在寻找不需要我安装 PHP.
任何扩展的功能或东西编辑:
我需要长格式整数,以便我可以比较它以进行 IP 范围查询。以下是 IPv6 范围查询的示例行:
"58569075684585412230123897272863293440","58569076873007849944088961176022548479","MU","Mauritius"
建议:
长存储不是正确的方法。使用,
string inet_ntop ( string $in_addr )
This function converts a 32bit IPv4, or 128bit IPv6 address (if PHP was built with IPv6 support enabled) into an address family appropriate string representation.
你也应该看到,
string inet_pton ( string $address )
inet_ntop() 例子
<?php
$packed = chr(127) . chr(0) . chr(0) . chr(1);
$expanded = inet_ntop($packed);
/* Outputs: 127.0.0.1 */
echo $expanded;
$packed = str_repeat(chr(0), 15) . chr(1);
$expanded = inet_ntop($packed);
/* Outputs: ::1 */
echo $expanded;
?>
范围比较
在PHP5.1.0、inet_pton
和inet_pton
中引入了以下两个函数。他们的目的是将人类可读的 IP 地址转换成他们打包的 in_addr
表示。由于结果不是纯二进制,我们需要使用 unpack
函数来应用按位运算符。
这两个函数都支持 IPv6 和 IPv4。唯一的区别是您如何从结果中解压缩地址。对于 IPv6,您将使用 A16 解压内容,对于 IPv4,您将使用 A4 解压。
为了把前面的放在一个透视图中,这里有一个小示例输出来帮助澄清:
// Our Example IP's
$ip4= "10.22.99.129";
$ip6= "fe80:1:2:3:a:bad:1dea:dad";
// ip2long examples
var_dump( ip2long($ip4) ); // int(169239425)
var_dump( ip2long($ip6) ); // bool(false)
// inet_pton examples
var_dump( inet_pton( $ip4 ) ); // string(4)
var_dump( inet_pton( $ip6 ) ); // string(16)
我们在上面证明了 inet_* 系列同时支持 IPv6 和 v4。我们的下一步是将打包结果转换为解包变量。
// Unpacking and Packing
$_u4 = current( unpack( "A4", inet_pton( $ip4 ) ) );
var_dump( inet_ntop( pack( "A4", $_u4 ) ) ); // string(12) "10.22.99.129"
$_u6 = current( unpack( "A16", inet_pton( $ip6 ) ) );
var_dump( inet_ntop( pack( "A16", $_u6 ) ) ); //string(25) "fe80:1:2:3:a:bad:1dea:dad"
注:当前函数returns数组的第一个索引。这相当于说 $array[0].
解包打包后,我们可以看到我们得到了与输入相同的结果。这是一个简单的概念证明,可确保我们不会丢失任何数据。
终于用上了,
if ($ip <= $high_ip && $low_ip <= $ip) {
echo "in range";
}
参考:php.net
好的,这是我最终解决它的方法:
function ipaddress_to_ipnumber($ipaddress) {
$pton = @inet_pton($ipaddress);
if (!$pton) { return false; }
$number = '';
foreach (unpack('C*', $pton) as $byte) {
$number .= str_pad(decbin($byte), 8, '0', STR_PAD_LEFT);
}
return base_convert(ltrim($number, '0'), 2, 10);
}