使用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 )

此函数转换32位IPv4或128位IPv6地址(如果PHP是在启用IPv6支持的情况下构建的)适当的字符串表示。

你也应该看到,

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;
?>

范围内比较

PHP 5.1.0中引入了以下两个函数:inet_ptoninet_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"

注意:当前函数返回数组的第一个索引。这相当于说$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);
}

https://inkplant.com/code/ipv6-to-number