如果 2 个 IPv6 地址相等,我如何签入 PHP?

How can I check in PHP if 2 IPv6-Adresses are equal?

我想检查 IP 是否在白名单中,但 IPv6 地址可以有不同的表示形式:

例如2001:0DB8:0:0:1::12001:0db8:0000:0000:0001:0000:0000:0001的缩写形式。

因此,字符串比较不起作用。我怎么知道两个地址相等?

使用inet_pton.

function is_ip_equal($ip1, $ip2) {
    return inet_pton($ip1) == inet_pton($ip2);
}

(但是,这仅在 PHP 未使用 --disable-ipv6 option 编译时有效。您可以使用 if (!defined('AF_INET6')) echo "IPv6 support was disabled"; 进行检查)。

inet_pton 不会去掉带括号的 IPv6 地址中的括号,这只对非常具体的用例很重要:inet_pton("[::1]") returns FALSE。这是因为括号内的地址在技术上不是有效的 IPv6 地址(相反,括号内的地址 包含 一个 IPv6 地址),即使当 IPv6 在 URL 中时括号是必需的。

这里是 Ipv6-only 函数:

$bothBracketsArray = array('[', ']');
function are_ipv6_equal($a, $b) {
    global $bothBracketsArray;
    return inet_pton(str_replace($bothBracketsArray, '', $a)) === inet_pton(str_replace($bothBracketsArray, '', $b));
}

$bothBracketsArray 是全局的,因此 PHP 不必每次都分配一个新数组或对其模板进行浅表克隆(或任何 PHP现在正在做)。

我自己的目的还需要比较端口号和处理 IPv4,因为我正在监视 netstat 的输出以查看哪个进程 PID 在套接字的另一端。

$bothBracketsArray = array('[', ']');
function doIpsAndPortsEqual($a, $b) {
    global $bothBracketsArray;
    $lastPosA = strrpos($a, ":"); // port #
    $lastPosB = strrpos($b, ":"); // port #
    if (substr($a, $lastPosA+1) !== substr($b, $lastPosB+1)) return false;
    $ipA = substr($a, 0, $lastPosA);
    $ipB = substr($a, 0, $lastPosB);
    if (strpos($ipA, ':') !== false) { // Ipv6
        return inet_pton(str_replace($bothBracketsArray, '', $ipA)) === inet_pton(str_replace($bothBracketsArray, '', $ipB));
    } else { // Ipv4
        return $ipA === $ipB;
    }
}