项目中需把IPV6 转成数字 方便保存数据库,利于节省空间和加速查询。废话不多说贴代码:
JavaScript:
BigInteger.js
//ipv6 转38为数字
function ip2long6(ip_address) {
var parts = [];
ip_address.split(':').forEach(function(it) {
var bin = parseInt(it, 16).toString(2);
while (bin.length < 16) {
bin = '0' + bin;
}
parts.push(bin);
});
var bin = parts.join('');
//需要引入js文件,我会在附件贴上
return bigInt(bin, 2).toString();
}
/**
* 位数补偿
* @param dividend
* @param divisor
* @returns {{quotient: (string|*), remainder: *}}
*/
function divide(dividend, divisor) {
var returnValue = '';
var remainder = 0;
var currentDividend = 0,
currentQuotient;
dividend.split('').forEach(function(digit, index) {
// use classical digit by digit division
if (currentDividend !== 0) {
currentDividend = currentDividend * 10;
}
currentDividend += parseInt(digit);
if (currentDividend >= divisor) {
currentQuotient = Math.floor(currentDividend / divisor);
currentDividend -= currentQuotient * divisor;
returnValue += currentQuotient.toString();
} else if (returnValue.length > 0) {
returnValue += '0';
}
if (index === dividend.length - 1) {
remainder = currentDividend;
}
});
return {
quotient: returnValue.length === 0 ? '0' : returnValue,
remainder: remainder,
};
}
/**
* 数字转ipv6
* @param input
* @param base
* @returns {string}
*/
function convertToIPv6(input, base) {
base = base || 10;
var blocks = [];
var blockSize = Math.pow(2, 16); // 16 bit per block
while (blocks.length < 8) {
var divisionResult = divide(input, blockSize);
// The remainder is the block value
blocks.unshift(divisionResult.remainder.toString(base));
// The quotient will be used as dividend for the next block
input = divisionResult.quotient;
}
return blocks.join(':');
}
PHP代码:
注:需要打开php.ini 里面的 extension=php_gmp.dll 如果没有dll 请自行下载。如果你是linux 请自行编译so
/**
* IPV6 地址转换为整数
* @param $ipv6
* @return string
* */
public function ip2long6($ipv6)
{
$ip_n = inet_pton($ipv6);
$bits = 15; // 16 x 8 bit = 128bit
$ipv6long = '';
while ($bits >= 0) {
$bin = sprintf("%08b", (ord($ip_n[$bits])));
$ipv6long = $bin . $ipv6long;
$bits--;
}
return gmp_strval(gmp_init($ipv6long, 2), 10);
}
/**
* 数字转为IPv6地址
* 数字长度38位
*/
public function long2ip_v6($dec)
{
if (function_exists('gmp_init')) {
$bin = gmp_strval(gmp_init($dec, 10), 2); //10进制 -> 2进制
} elseif (function_exists('bcadd')) {
$bin = '';
do {
$bin = bcmod($dec, '2') . $bin; //10进制 -> 2进制,获取$dec/2的余数
$dec = bcdiv($dec, '2', 0); // dec/2的值,0表示小数点后位数
} while (bccomp($dec, '0'));
} else {
// trigger_error('GMP or BCMATH extension not installed!', E_USER_ERROR);
return 'GMP or BCMATH extension not installed!';
}
$bin = str_pad($bin, 128, '0', STR_PAD_LEFT); // 给2进制值补0
$ip = array();
for ($bit = 0; $bit <= 7; $bit++) {
$bin_part = substr($bin, $bit * 16, 16); // 每16位分隔
$ip[] = dechex(bindec($bin_part)); // 2进制->10进制->16进制
}
$ip = implode(':', $ip);
// inet_pton:将可读的IP地址转换为其压缩的in_addr表示形式
// inet_ntop:将打包的Internet地址转换为可读的表示形式
return inet_ntop(inet_pton($ip));
}