php: ip2long restituendo val negativo

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); } } 

quella function esegue lo stesso codice della function bundle php ip2long. tuttavia, quando stampo questi 2 valori, ottengo 2 ritorni diversi. perché? (im utilizzando php 5.2.10 su un ambiente di una palude).

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

Applicato e continuato qui: mostra il mio paese in base al mio IP, mysql ottimizzato

 glopes @ nebm: ~ $ php -r "printf ('% u', -931792879);"
 3363174417

Ecco qua. La mia ipotesi è che tu sia su un sistema con 32 bit int e il tuo ip_address_to_number restituisca effettivamente un float.

Vedete, con 32 bit int, il numero integer positivo massimo è (2^31) - 1 = 2 147 483 647 , quindi l'integer si avvolge.

Se vuoi simulare il comportmento della function PHP, fai:

 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); } } 

(a proposito, split è stato deprecato)

Prova questo invece:

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

sprintf lo scriverà quindi come un numero integer senza segno.

  $ips[3] = 17 + $ips[2] * 256 = 248 * 256 = 63488 + $ips[1] * 65536 = 117 * 65536 = 7667712 + $ips[0] * 16777216 = 200 * 16777216 = 3355443200 = 3363174417 

Il valore integer massimo di PHP (32 bit) è 2147483647, ovvero <3363174417

Citando dalla pagina di manuale PHP ip2long ()

Nota: poiché il tipo integer di PHP è firmato e molti indirizzi IP generano numbers interi negativi, è necessario utilizzare il formattatore "% u" di sprintf () o printf () per get la rappresentazione della string dell'indirizzo IP non firmato.

Puoi usare –

 // 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))); } 
 <?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); } ?> 

Sono stati effettuati alcuni test delle performance per confrontare l'esecuzione di ip2long tramite sprintf vs arrays explode e quindi times o bitwise shift:

 <?php header ('Content-Type: text/plain'); function ip_range($start, $count) { $start = ip2long($start); return arrays_map('long2ip', range($start, $start + $count) ); } $iterations = 500000; $results = arrays(); $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'] = arrays ('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'] = arrays ('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'] = arrays ('total' => $time, 'cycles' => $iterations, 'average' => ($time / $iterations) . 's', 'speed' => ($iterations/$time) . ' hashes per second.' ); die(var_dump($results)); 

Questi sono i risultati:

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

Quando avvolgono bit per bit e si moltiplicano in sprintf , sono più lenti di ip2long ma, poiché non è necessario, sono più veloci.