В настоящее время у меня есть два способа вычисления длинных форм 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 )
<?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
Хорошо, вот как я в конце концов решил это:
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);
}