Расчет длинного номера формы IP-адреса для IPv6 по сравнению с IPv4 с использованием переполнения стека

В настоящее время у меня есть два способа вычисления длинных форм 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"

1

Решение

Предложения:

Хранение в длинном не является правильным способом для этого. Использование,

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_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"

Примечание. Текущая функция возвращает первый индекс массива. Это равносильно тому, чтобы сказать $ array [0].

После распаковки и упаковки видно, что мы достигли того же результата, что и входные данные. Это простое подтверждение концепции, гарантирующей, что мы не теряем никаких данных.

Наконец использовать,

if ($ip <= $high_ip && $low_ip <= $ip) {
echo "in range";
}

Ссылка: php.net

2

Другие решения

Хорошо, вот как я в конце концов решил это:

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

0

По вопросам рекламы [email protected]