2016-02-04 21 views
1

我正在使用IP2Location数据库来查找IPv6地址的国家代码。他们有一个method将IPv6地址转换为可用于查询其数据库的(大)号码。将数字还原为IPv6字符串表示形式

$ipv6 = '2404:6800:4001:805::1006'; 
$int = inet_pton($ipv6); 
$bits = 15; 

$ipv6long = 0; 

while($bits >= 0){ 
    $bin = sprintf("%08b", (ord($int[$bits]))); 

    if($ipv6long){ 
     $ipv6long = $bin . $ipv6long; 
    } 
    else{ 
     $ipv6long = $bin; 
    } 
    $bits--; 
} 
$ipv6long = gmp_strval(gmp_init($ipv6long, 2), 10); 

在这种情况下,$ipv6long将47875086426098177934326549022813196294.

现在我想知道这样的数量是否可以恢复到地址的IPv6字符串表示。如果是这样,怎么样?

+2

这是一个普通的整数,你的'2404 ...'版本是十六进制的。所以基本上这只是“如何将整数转换为十六进制表示”。只要记住'::'代表一个全零的序列,另一个':'只是用于16位块的可视分离。 –

+0

@MarcB谢谢,这让我走上正轨。准备好后会发布我的代码。 – RonaldPK

回答

2

inet_ntop()可以格式化IPv6地址,但您需要先转换为压缩字符串(每个字符为数字的一个字节的16个字符的字符串)。

function ipv6number2string($number) { 
    // convert to hex 
    $hex = gmp_strval(gmp_init($number, 10), 16); 
    // pad to 32 chars 
    $hex = str_pad($hex, 32, '0', STR_PAD_LEFT); 
    // convert to a binary string 
    $packed = hex2bin($hex); 
    // convert to IPv6 string 
    return inet_ntop($packed); 
} 

echo ipv6number2string(47875086426098177934326549022813196294); 
+0

有什么办法可以不使用GMP扩展? – jcarlosweb

1

要回答我的问题:这将工作:

function ipv6number2string($number) { 
    // thanks to joost @ http://php.net/manual/en/function.dechex.php 
    $hexvalues = array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'); 
    $hexval = ''; 
    while($number != '0') { 
     $hexval = $hexvalues[bcmod($number,'16')].$hexval; 
     $number = bcdiv($number,'16',0); 
    } 

    // now format it with colons 
    $str = ''; 
    preg_replace_callback('/([a-f0-9]{4})/', function($m) use (&$str) { 
     if (empty($str)) { 
      $str = is_numeric($m[0]) ? intval($m[0]) : $m[0]; 
     } else { 
      $str .= ':' . (is_numeric($m[0]) ? intval($m[0]) : $m[0]); 
     } 
    }, $hexval); 
    return preg_replace(array('/:0/', '/:{3,}/'), '::', $str); 
} 

echo ipv6number2string(47875086426098177934326549022813196294); 

将显示2404:6800:4001:805 :: 1006。

+0

这将忽略前导零和折叠多个组(只允许一个)。用'“79226953588445004435050987520”'尝试一下,你会得到一个无效的IP。使用'inet_ntop()'查看我的答案,以获得适用于任何地址的版本。 – mcrumley

+0

@mcrumley谢谢,这的确更好。 – RonaldPK

相关问题