lovecn / lovecn.github.io

个人记录
5 stars 5 forks source link

PHP ip2long() 为负数 #26

Open lovecn opened 9 years ago

lovecn commented 9 years ago
32 bits ip2long(): -2147483648 ~ 214748364764 
64 bits ip2long(): 0 ~ 4294967295 
ip地址在mysql的存储可以使用varchar(15)或bigint来存储,如果用bigint,php存入时:$ip = ip2long($ip);mysql取出时:SELECT INET_ATON(ip) FROM table ...
php取出时:$ip = long2ip($ip);

//php中可以使用ip2long来转换,具体算法如下:A*256*256*256+B*256*256+C*256+D
function iptolong($ip){
    //先把ip分为四段,$ip1,$ip2,$ip3,$ip4
    list($ip1,$ip2,$ip3,$ip4)=explode(".",$ip);
    //然后第一段乘以256的三次方,第二段乘以256的平方,第三段乘以256
    $ipLong= $ip1*pow(256,3)+$ip2*pow(256,2)+$ip3*256+$ip4;
    return $ipLong;
    //return intval($ipLong);这样会产生负数,因为intval在32和64位操作系统最大值是不同的,32系统: -2147483648 ~ 214748364764 64系统: 0 ~ 9223372036854775807,因此32系统intval('1000000000000')返回 2147483647
}
//ip2long()在32位系统的测试
echo PHP_INT_MAX;//2147483647
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()在64位系统的测试
echo PHP_INT_MAX;//9223372036854775807
ip2long('127.255.255.255'); // 2147483647 = 十进位的最大值 
ip2long('255.255.255.255'); // 4294967295 
ip2long('255.255.255.254'); // 4294967294 
ip2long('192.168.1.2'); // 3232235778 

function iptolong($ip){
    list($ip1,$ip2,$ip3,$ip4)=explode(".",$ip);
    return ($ip1<<24)|($ip2<<16)|($ip3<<8)|($ip4);
}
//相应的long2ip算法:https://my.oschina.net/goal/blog/198049
function longtoip($ip_long) {
    $ip1 = ($ip_long >> 24) & 0xff; // 跟0xff做与运算的目的是取低8位
    $ip2 = ($ip_long >> 16) & 0xff;
    $ip3 = ($ip_long >> 8) & 0xff;
    $ip4 = $ip_long & 0xff;
    return $ip1 . '.' . $ip2 . '.' . $ip3 . '.' . $ip4;
}
function longtoip($ip_long)  {
        $d = $ip_long%256;
        $c = (($ip_long-$d)/256)%256;
        $b = (($ip_long-($c*256)-$d)/(256*256))%256;
        $a = (($ip_long-($b*256*256)-$c*256-$d)/(256*256*256))%256;
        return $a.".".$b.".".$c.".".$d;  
}
//javascript相应的long2ip算法:
var ip_long = 2635544666;
var ip1 = (ip_long >> 24) & 0xff;
var ip2 = (ip_long >> 16) & 0xff;
var ip3 = (ip_long >> 8) & 0xff;
var ip4 = ip_long & 0xff;
console.log(ip1 + "." + ip2 + "." + ip3 + "." + ip4);//157.23.56.90
console.log(((157 << 24) | (23 << 16) | (56 << 8) | 90) >>> 0);

$ip = '10.1.1.1';
$ip_long = ip2long($ip);//如果ip无效返回false
echo ip2long('058.99.11.1'); // null
echo ip2long('58.099.11.1'); // null

echo $ip_long;  // 167837953
echo long2ip($ip_long); // 10.1.1.1

//php中将IP转换成整型的函数ip2long在IP比较大的情况下,会变成负数
>>> ip2long('192.168.1.38');
=> -1062731482
//解决方法一:bindec,decbin转换
>>> bindec(decbin(ip2long('192.168.1.38')));
=> 3232235814.0
//解决方法二:使用%u来格式化为无符号整型
$ip = '192.168.1.38';
$ip_long = sprintf('%u',ip2long($ip));
echo $ip_long.PHP_EOL;  // 3232261476 
echo long2ip($ip_long); // 192.168.1.38
//解决方法三:使用iptolong方法

//mysql中相应转换:
>  SELECT INET_ATON('209.207.224.40');
3520061480 
>  SELECT INET_NTOA(3520061480);
'209.207.224.40'

//http://blog.longwin.com.tw/2010/04/php-ip2long-negative-number-fix-2010/