PHP ip2long() 回傳值為負數 的 解法

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

相關網頁

作者: Tsung

對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.

在〈PHP ip2long() 回傳值為負數 的 解法〉中有 2 則留言

發表迴響

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料