php 计算ip段开始ip

php 通过CIDR 计算ip段开始ip 适用ipv6与ipv4

/**
 * CIDR 计算段开始ip
 * @param string $ipData 格式 ipv4"xxx.xxx.xxx.xxx/xx"或 ipv6:"xxxx:xxxx::xxxx/xx"
 * @return false|string
 */
function cidrHandle($ipData)
{
    list($item['ip'], $item['mask']) = explode('/', $ipData);
    $mask = (int)$item['mask'];
    $ip = ipToBin($item['ip']);
    if (filter_var($item['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
        //ip4
        if ($mask > 32) return false;
        $mask = 0xFFFFFFFF << (32 - $mask) & 0xFFFFFFFF;
        $mask = base_convert($mask, 10, 2);
        $ipbin = ($ip & $mask);
    } else {
        if ($mask > 128) return false;
        //一次做与运算数字长度128位,超过cpu位数,所以按32长度分成4段 ,
        $binArr = str_split($ip, 32);
        if ($mask <= 32) {
            $bitIndex = 0;
            $tagLen = 32;
        } elseif ($mask <= 64) {
            $bitIndex = 1;
            $tagLen = 64;
        } elseif ($mask <= 96) {
            $bitIndex = 2;
            $tagLen = 96;
        } else {
            $bitIndex = 3;
            $tagLen = 128;
        }
        $mask = 0xFFFFFFFF << ($tagLen - $mask) & 0xFFFFFFFF;
        $mask = base_convert($mask, 10, 2);
        //做与运算的段,后面段直接置零
        $binArr[$bitIndex] = ($binArr[$bitIndex] & $mask);
        for ($i = $bitIndex + 1; $i <= 3; $i++) {
            $binArr[$i] = str_repeat("0",32);
        }
        $ipbin = implode('', $binArr);
    }
    $ipStart = binToIp($ipbin);
    $outIpData = $ipStart . '/' . $item['mask'];
    return $outIpData;
}

/**
 *  IPv4|IPv6 转换 bin地址
 * @param string $ip ipv4|ipv6
 * @return false|string 字符串格式二进制数
 */

function ipToBin($ip)
{
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
        $bin = base_convert(ip2long($ip), 10, 2);
        $pad = 32 - strlen($bin);
        for ($i = 1; $i <= $pad; $i++) {
            $bin = "0" . $bin;
        }
        return $bin;
    }
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
        return false;
    }
    if (($ip_n = inet_pton($ip)) === false) {
        return false;
    }
    // 16 x 8 bit = 128bit (ipv6)
    $bits = 15;
    $ipbin = "";
    while ($bits >= 0) {
        $bin = sprintf("%08b", (ord($ip_n[$bits])));
        $ipbin = $bin . $ipbin;
        $bits--;
    }
    return $ipbin;
}

/**
 * 转换bin地址为IPv6 或IPv4
 * @param string $bin 字符串格式二进制数
 * @return false|string  IPv4|IPv6地址
 */
function binToIp($bin)
{
    if (strlen($bin) <= 32) // 32bits (ipv4)
    {
        return long2ip(base_convert($bin, 2, 10));
    }
    if (strlen($bin) != 128) {
        return false;
    }

    $bits = 0;
    $ipv6 = "";
    while ($bits <= 7) {
        $bin_part = substr($bin, ($bits * 16), 16);
        $ipv6 .= dechex(bindec($bin_part)) . ":";
        $bits++;
    }
    return inet_ntop(inet_pton(substr($ipv6, 0, -1)));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值