Detailed explanation of IP address and integer number conversion in PHP

  • 2021-07-13 04:52:07
  • OfStack

Conversion of IP to integer storage is a major trend of database optimization. Many people still use string storage when storing IP. String index consumes a lot of resources than integer index, especially when the amount of data in the table is large, and the data of a certain ip segment is queried. Today's ip refers to ip4, and ip6 is not within the scope of this article.

System functions ip2long and long2ip
PHP has a built-in function ip2long that converts an ip address to an integer type.


$ip = '210.110.11.49';
echo ip2long($ip);

Output:

-764540111

The output integer is minus because the result we get is a signed integer. The maximum value of a signed integer is 2147483647. To convert the result to an unsigned type, you can write this:

3530427185

Convert integers back to ip addresses using long2ip


$ip = '210.110.11.49';
$ip_int = ip2long($ip);
echo $ip."<br />";
echo $ip_int."<br />";
echo long2ip($ip_int);

Output:

210.110.11.49
-764540111
210.110.11.49

It can be seen from the results that ip and integer types can be completed by functions.

System function small bug

In this bug online 1 search is, to the effect that a certain section of ip is added with a leading 0. Let's take a look at this bug example first


$ip = '210.110.011.49';
$ip_int = ip2long($ip);
echo $ip."<br />";
echo $ip_int."<br />";
echo long2ip($ip_int);

Output:

210.110.011.49
-764540623
210.110.9.49

The conversion results do not match. Let's try to prefix the number in paragraph 1 of ip with a leading 0, and then look at it


$ip = '021.110.11.49';
$ip_int = ip2long($ip);
echo $ip."<br />";
echo $ip_int."<br />";
echo long2ip($ip_int);

Output:

021.110.11.49
292424497
17.110.11.49

The conversion results are all wrong. In the above examples, the conversion result is wrong after adding the preamble 0, and the reverse result does not match the original conversion ip.

Transformation principle

There are currently two algorithms:
Paragraph 1 times 256 to the third power, paragraph 2 times 256 squared, paragraph 3 times 256, and finally sum


$ip = '0210.110.11.49';
 
function ipToInt($ip){
    $iparr = explode('.',$ip);
    $num = 0;
    for($i=0;$i<count($iparr);$i++){
        $num += intval($iparr[$i]) * pow(256,count($iparr)-($i+1));
    }
    return $num;
}
 
echo  $ip.'<br />';
$ip_int = ipToInt($ip);
echo $ip_int.'<br />';
echo long2ip($ip_int);

Output:

0210.110.11.49
3530427185
210.110.11.49

Step 2: Pass the bitwise operator


$ip = '0210.110.11.49';
 
function ipToInt($ip){
    $iparr = explode('.',$ip);
    return (intval($iparr[0]<<24))|(intval($iparr[1])<<16)|(intval($iparr[2])<<8)| (intval($iparr[3]));
}
 
echo  $ip.'<br />';
$ip_int = ipToInt($ip);
echo $ip_int.'<br />';
echo long2ip($ip_int);

Output:

0210.110.11.49
-764540111
210.110.11.49

Check whether IP is legal

1. Self-traversal detection


function check_ip($ip){
    $iparr = explode('.',$ip);
    foreach($iparr as $v){ if($v>255) return false; }
    return true;
}
 
echo '210.285.11.49,';
var_dump(check_ip('210.285.11.49'));
echo '<br />';
echo '210.205.11.49,';
var_dump(check_ip('210.205.11.49'));
[code] Output:
[code]
210.285.11.49,bool(false)
210.205.11.49,bool(true)

Section 2. Using ip2long to return

function check_ip($ip){
    if(ip2long($ip)) return true;
    return false;
}
 
echo '210.285.11.49,';
var_dump(check_ip('210.285.11.49'));
echo '<br />';
echo '210.205.11.49,';
var_dump(check_ip('210.205.11.49'));

Output:

210.285.11.49,bool(false)
210.205.11.49,bool(true)

Postscript

Many people write ip into the int-type fields by ip2long conversion. However, the values obtained by ip2long function are different on different system platforms, so the ip obtained by long2ip may not conform to the original ip when reading data from the database and reversing ip
If it is mysql, you can use mysql system functions INET_ATON and INET_NTOA, or use bigint type processing, or write your own function.


Related articles: