代码之家  ›  专栏  ›  技术社区  ›  Andres SK

php:ip2long返回负val

  •  14
  • Andres SK  · 技术社区  · 15 年前
    function ip_address_to_number($IPaddress) { 
         if(!$IPaddress) {
          return false;
         } else {
          $ips = split('\.',$IPaddress);
          return($ips[3] + $ips[2]*256 + $ips[1]*65536 + $ips[0]*16777216);
         }
    }
    

    该函数执行与php捆绑函数ip2long相同的代码。但是,当我打印这两个值时,会得到两个不同的返回值。为什么?(我在wamp环境中使用php 5.2.10)。

    ip2long('200.117.248.17'); //returns **-931792879**
    
    ip_address_to_number('200.117.248.17'); // returns **3363174417**
    

    应用并在此处继续: Showing my country based on my IP, mysql optimized

    6 回复  |  直到 8 年前
        1
  •  9
  •   Artefacto    15 年前
    glopes@nebm:~$ php -r "printf('%u', -931792879);"
    3363174417
    

    你走吧。我猜你在一个32位整数的系统上 ip_address_to_number 实际上是返回一个浮动。

    你看,32位整数的最大正整数是 (2^31) - 1 = 2 147 483 647 ,所以整数环绕。

    如果要模拟PHP函数的行为,请执行以下操作:

    function ip_address_to_number($IPaddress) { 
     if(!$IPaddress) {
      return false;
     } else {
      $ips = split('\.',$IPaddress);
      return($ips[3] | $ips[2] << 8 | $ips[1] << 16 | $ips[0] << 24);
     }
    }
    

    (顺便说一下, split 已弃用)

        2
  •  31
  •   webbiedave    15 年前

    试试这个:

    $ip = sprintf('%u', ip2long($_SERVER['REMOTE_ADDR']));
    

    sprintf 然后将其写为无符号整数。

        3
  •  5
  •   Mark Baker    15 年前
      $ips[3]                             = 17
    + $ips[2] * 256 = 248 * 256           = 63488
    + $ips[1] * 65536 = 117 * 65536       = 7667712
    + $ips[0] * 16777216 = 200 * 16777216 = 3355443200
                                          = 3363174417
    

    php最大整数值(32位)为2147483647,即3363174417

    从ip2long()php手册页引用

    注意:因为php的整数类型是 签名,许多IP地址将 结果为负整数,需要 使用sprintf()的“%u”格式化程序 或printf()获取字符串 无符号IP的表示 地址。

        4
  •  1
  •   user2253362    12 年前

    你可以使用-

    // IP Address to Number
    function inet_aton($ip)
    {
        $ip = trim($ip);
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) return 0;
        return sprintf("%u", ip2long($ip));  
    }
    
    // Number to IP Address
    function inet_ntoa($num)
    {
        $num = trim($num);
        if ($num == "0") return "0.0.0.0";
        return long2ip(-(4294967295 - ($num - 1))); 
    }
    
        5
  •  0
  •   Mohammad Lotfi    10 年前
    <?php
    function _ip2long($input)
    {
        $r = null;
        if (is_string($input))
        {
            $_input = trim($input);
            if (filter_var($_input, FILTER_VALIDATE_IP))
            {
                $PRE_r = explode('.', $_input);
                $r = ($PRE_r[0] * pow(256, 3)) + ($PRE_r[1] * pow(256, 2)) + ($PRE_r[2] * 256) + ($PRE_r[0]);
            } else
            { 
                $r = false;
            }
        } else
        {
            $r = false;
        }
        return ($r);
    }
    $out = _ip2long('127.0.0.1');
    if (false === $out)
    {
      print('Invalid IP');
    } else
    {
      print($out);
    }
    ?>
    
        6
  •  0
  •   Kristian Williams    10 年前

    做了一些性能测试比较运行 ip2long 通过 sprintf vs数组分解,然后按次或按位移位:

    <?php
        header ('Content-Type: text/plain');
    
        function ip_range($start, $count) {
            $start = ip2long($start);
            return array_map('long2ip', range($start, $start + $count) );
        }
    
        $iterations = 500000;
        $results = array();
        $ips = ip_range('192.168.1.1', $iterations);
        $time = microtime(true);
        foreach ($ips as $ip) {
            $result = sprintf('%u', ip2long($ip));
        }
        $time = microtime(true) - $time;
        $results['ip2long'] = array ('total' => $time, 'cycles' => $iterations, 'average' => ($time / $iterations) . 's', 'speed' => ($iterations/$time) . ' hashes per second.' );
    
        $time = microtime(true);
        foreach ($ips as $ip) {
            $aIp = explode('.', $ip);
            if (count($aIp) == 4) {
                $result = /*sprintf('%u',*/ $aIp[0]*16777216 + $aIp[1]*65536 + $aIp[2]*256 + $aIp[3] /*)*/;
            }
            else
            {
                $result = false;
            }
        }
        $time = microtime(true) - $time;
        $results['explode multiple'] = array ('total' => $time, 'cycles' => $iterations, 'average' => ($time / $iterations) . 's', 'speed' => ($iterations/$time) . ' hashes per second.' );
    
        $time = microtime(true);
        foreach ($ips as $ip) {
            $aIp = explode('.', $ip);
            if (count($aIp) == 4) {
                $result = /*sprintf('%u',*/ $aIp[3] | $aIp[2] << 8 | $aIp[1] << 16 | $aIp[0] << 24 /*)*/;
            }
            else
            {
                $result = false;
            }
        }
        $time = microtime(true) - $time;
        $results['explode bitwise'] = array ('total' => $time, 'cycles' => $iterations, 'average' => ($time / $iterations) . 's', 'speed' => ($iterations/$time) . ' hashes per second.' );
    
    
        die(var_dump($results));
    

    结果如下:

    array(3) {
    
    
    ["ip2long"]=>
      array(4) {
        ["total"]=>
        float(0.92530012130737)
        ["cycles"]=>
        int(500000)
        ["average"]=>
        string(19) "1.8506002426147E-6s"
        ["speed"]=>
        string(34) "540365.21609177 hashes per second."
      }
      ["explode multiple"]=>
      array(4) {
        ["total"]=>
        float(0.91870212554932)
        ["cycles"]=>
        int(500000)
        ["average"]=>
        string(19) "1.8374042510986E-6s"
        ["speed"]=>
        string(34) "544246.04678153 hashes per second."
      }
      ["explode bitwise"]=>
      array(4) {
        ["total"]=>
        float(0.9184091091156)
        ["cycles"]=>
        int(500000)
        ["average"]=>
        string(19) "1.8368182182312E-6s"
        ["speed"]=>
        string(34) "544419.68730197 hashes per second."
      }
    }
    

    当按位包装并在 把格式数据写成串 它们比 IP2Lon 但由于不需要,所以速度更快。