在Ipv4中,我们可以使用ip2long它将其转换为数字,
如何在PHP中将ipv6压缩为数字转换?
我试过inet_pton而且它不起作用.
$ip_1='2001:0db8:85a3:0000:0000:8a2e:0370:7334';
$ip_2='2001:11ff:ffff:f';//Compressed
echo inet_pton($ip_1);
//OUTPUT ??.ps4
echo inet_pton($ip_2);
//OUTPUT Warning: inet_pton(): Unrecognized address 2001:11ff:ffff:f
Run Code Online (Sandbox Code Playgroud)
Gla*_*vić 10
$ip = 'fe80:0:0:0:202:b3ff:fe1e:8329';
$dec = ip2long_v6($ip);
$ip2 = long2ip_v6($dec);
// $ip = fe80:0:0:0:202:b3ff:fe1e:8329
// $dec = 338288524927261089654163772891438416681
// $ip2 = fe80::202:b3ff:fe1e:8329
Run Code Online (Sandbox Code Playgroud)
function ip2long_v6($ip) {
$ip_n = inet_pton($ip);
$bin = '';
for ($bit = strlen($ip_n) - 1; $bit >= 0; $bit--) {
$bin = sprintf('%08b', ord($ip_n[$bit])) . $bin;
}
if (function_exists('gmp_init')) {
return gmp_strval(gmp_init($bin, 2), 10);
} elseif (function_exists('bcadd')) {
$dec = '0';
for ($i = 0; $i < strlen($bin); $i++) {
$dec = bcmul($dec, '2', 0);
$dec = bcadd($dec, $bin[$i], 0);
}
return $dec;
} else {
trigger_error('GMP or BCMATH extension not installed!', E_USER_ERROR);
}
}
function long2ip_v6($dec) {
if (function_exists('gmp_init')) {
$bin = gmp_strval(gmp_init($dec, 10), 2);
} elseif (function_exists('bcadd')) {
$bin = '';
do {
$bin = bcmod($dec, '2') . $bin;
$dec = bcdiv($dec, '2', 0);
} while (bccomp($dec, '0'));
} else {
trigger_error('GMP or BCMATH extension not installed!', E_USER_ERROR);
}
$bin = str_pad($bin, 128, '0', STR_PAD_LEFT);
$ip = array();
for ($bit = 0; $bit <= 7; $bit++) {
$bin_part = substr($bin, $bit * 16, 16);
$ip[] = dechex(bindec($bin_part));
}
$ip = implode(':', $ip);
return inet_ntop(inet_pton($ip));
}
Run Code Online (Sandbox Code Playgroud)
$ ip_2不是有效的IPv6地址.你需要在那里的"::"表示零遗漏点.
如果你有一个
$ip_2='2001::11ff:ffff:f';
$ip_2='2001:11ff::ffff:f';
$ip_2='2001:11ff:ffff::f';
Run Code Online (Sandbox Code Playgroud)
那么inet_pton()应该可以正常工作.
正如已经暗示的那样,PHP没有128整数类型,所以你能得到的最好的是二进制字符串中的数字字符串 inet_pton()给你...是的,就是这样,这就是为什么它看起来很奇怪.如果你看一下这些字符串的位,你会发现它们正是你所期望的.
以下是如何将二进制字符串扩展为数字字符串(str_pad()中缺少参数"0"):
/**
* @param string $ip A human readable IPv4 or IPv6 address.
* @return string Decimal number, written out as a string due to limits on the size of int and float.
*/
function ipv6_numeric($ip) {
$binNum = '';
foreach (unpack('C*', inet_pton($ip)) as $byte) {
$binNum .= str_pad(decbin($byte), 8, "0", STR_PAD_LEFT);
}
return base_convert(ltrim($binNum, '0'), 2, 10);
}
Run Code Online (Sandbox Code Playgroud)
请注意,所有答案都会导致大IP地址的结果不正确,或者正在经历一个非常复杂的过程来接收实际数字.从IPv6地址检索实际的整数值需要两件事:
--with-gmp)有了两个先决条件,转换就像下面这样简单:
$ip = 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff';
$int = gmp_import(inet_pton($ip));
echo $int; // 340282366920938463463374607431768211455
Run Code Online (Sandbox Code Playgroud)
返回的二进制数字打包in_addr表示inet_pton已经是整数,可以直接导入GMP,如上所示.无需特殊转换或任何其他操作.
请注意,反过来也同样简单:
$int = '340282366920938463463374607431768211455';
$ip = inet_ntop(str_pad(gmp_export($int), 16, "\0", STR_PAD_LEFT));
echo $ip; // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
Run Code Online (Sandbox Code Playgroud)
因此,构建两个所需的函数非常简单:
function ipv6_to_integer($ip) {
return (string) gmp_import(inet_pton($ip));
}
function ipv6_from_integer($integer) {
return inet_ntop(str_pad(gmp_export($integer), 16, "\0", STR_PAD_LEFT));
}
Run Code Online (Sandbox Code Playgroud)