PHP 和 JavaScript IPV6与数字之间的转换, Converted To IPv6 address

项目中需把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));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值