PHP 的 ip2long 是將 IP 位址轉換為數值的 function.
ip2long() 轉出來的數值應該都是正整數, 但是在某些機器轉出負數, 剛開始以為是 PHP 版本問題, 後來做些測試, 確定是系統版本 32bits 和 64bits 的問題.
- 32 bits ip2long(): -2147483648 ~ 214748364764
- 64 bits ip2long(): 0 ~ 4294967295
測試
<?php
// 自己做轉換, 這方法計算出來的數值是正確的.(32bits / 64bits 皆正確)
function iptolong($ip)
{
list($a, $b, $c, $d) = split('\.', $ip);
$ip_long = (($a * 256 + $b) * 256 + $c) * 256 + $d;return $ip_long;
}
?>
另外做測試, 於 return 值加上 intval(), 如下述:
<?php
// 這樣子的數值就會產生負數.
function iptolong($ip)
{
list($a, $b, $c, $d) = split('\.', $ip);
$ip_long = (($a * 256 + $b) * 256 + $c) * 256 + $d;return intval($ip_long);
}
?>
intval 在 32 bits / 64 bits 最大值是不同的, 於 intval() 裡面有寫到下述:
The maximum value depends on the system.
32 bit systems have a maximum signed integer range of -2147483648 to 2147483647.
So for example on such a system, intval('1000000000000') will return 2147483647.
The maximum signed integer value for 64 bit systems is 9223372036854775807.
另外做其它測試:
ip2long() 於 32bits 的系統測試
- ip2long('127.255.255.255'); // 2147483647 = 十進位的最大值
- ip2long('255.255.255.255'); // -1
- ip2long('255.255.255.254'); // -2
- ip2long('192.168.1.2'); // -1062731518
ip2long() 於 64bits 的系統測試
- ip2long('127.255.255.255'); // 2147483647 = 十進位的最大值
- ip2long('255.255.255.255'); // 4294967295
- ip2long('255.255.255.254'); // 4294967294
- ip2long('192.168.1.2'); // 3232235778
知道問題是 32bits 系統造成的, 就很好解決囉~
解法1 - 自己轉換
<?php
function iptolong($ip)
{
list($a, $b, $c, $d) = split('\.', $ip);
return (($a * 256 + $b) * 256 + $c) * 256 + $d;
}
?>
解法2 - 轉成二進位, 再轉回十進位
<?php
// bindec 只吃 string, 回傳 double
// decbin 會回傳 string
echo bindec(decbin(ip2long('192.168.1.2'))); // 3232235778
// 此方法我也有點不太懂, 忘記從哪邊看到的解法.
?>
解法3 - 官方建議的解法 (推薦用此方法)
<?php
// 直接印值, 使用 printf("%u")
printf("%u", ip2long('192.168.1.2')); // 3232235778// 回傳值(於 function 或 echo 等), 使用 sprintf("%u")
echo sprintf("%u", ip2long('192.168.1.2')); // 3232235778
?>
另外 於此篇 (PHP 的 ip2long 有 Bug) 看到的案例如下:
<?php
echo ip2long('058.99.11.1'); // null
echo ip2long('58.099.11.1'); // null
?>
若是會有這種情況, 用 解法1 即可解決.
MySQL 的 ip2long - INET_ATON()
- SELECT INET_ATON('209.207.224.40');
3520061480 - SELECT INET_NTOA(3520061480);
'209.207.224.40' - 詳見: MySQL Reference Manual
64 bits ip2long(): 0 ~ 42949672945
文章里面的42949672945
正确的数字应该是4294967295
感謝指點, 寫錯了~