zoukankan      html  css  js  c++  java
  • php计算网段内所有IP,分配子网段

    由于最近业务需要,写了个获取网段内所有IP的函数,以及分配可用子网段的函数

    /**
     * 根据网段获取计算所有IP
     * @param string $segment 网段 '139.217.0.1/24'
     * @return array IP列表 ['139.217.0.1','139.217.0.2'……]
     */
    function getIpBySegment($segment)
    {
        $segmentInfo = explode("/", $segment);//['139.217.0.1',24]
        $beginIpArray = explode(".", $segmentInfo[0]);//[139,217,0,1]
        $mask = intval($segmentInfo['1']);//24
        $endIp = array();
        foreach ($beginIpArray as $ipKey => $item) {
            $beginFlag = 8 * ($ipKey);//0   8   16  24
            $endFlag = 8 * ($ipKey + 1);//8   16  24  32
            $decbinItem = str_pad(decbin($item), 8, "0", STR_PAD_LEFT);
            $endIp[] = $mask >= $endFlag ? $item : ($mask > $beginFlag ? bindec(str_pad(substr($decbinItem, 0, $mask - $beginFlag), 8, "1", STR_PAD_RIGHT)) : ($ipKey <= 2 ? pow(2, 8) - 1 : pow(2, 8) - 1));
        }
        $ipArray = array();
        for ($beginIp[0] = $beginIpArray[0]; $beginIp[0] <= $endIp[0]; $beginIp[0]++) {
            for ($beginIp[1] = $beginIpArray[1]; $beginIp[1] <= $endIp[1]; $beginIp[1]++) {
                for ($beginIp[2] = $beginIpArray[2]; $beginIp[2] <= $endIp[2]; $beginIp[2]++) {
                    for ($beginIp[3] = $beginIpArray[3]; $beginIp[3] <= $endIp[3]; $beginIp[3]++) {
                        $ipArray[] = implode(".", $beginIp);
                    }
                }
            }
        }
        return $ipArray;
    }
    /**
     * 在指定网段中分配子网段
     * @param string $segment 指定网段
     * @param int $ipNum 需要的IP数
     * @param array $usedIpArray 不可用(已经使用)的IP,默认为空数组
     * @return bool|string 成功则返回分配的网段
     */
    function allocateSegment($segment, $ipNum, $usedIpArray = [])
    {
        $usedIpArray = empty($usedIpArray) ? [] : array_flip($usedIpArray);
        //计算需要多少个IP
        $i = 0;
        $ipCount = pow(2, $i);
        while ($ipCount < $ipNum) {
            $i++;
            $ipCount = pow(2, $i);
        }
        $newMask = 32 - $i;
        //大网段的开始和结束IP
        $segmentInfo = explode("/", $segment);//['139.217.0.1',24]
        $beginIpArray = explode(".", $segmentInfo[0]);//[139,217,0,1]
        $mask = intval($segmentInfo['1']);//24
        if ($newMask < $mask) {
            return false;
        }
        $endIp = array();
        $step = [];
        foreach ($beginIpArray as $ipKey => $item) {
            $beginFlag = 8 * ($ipKey);//0   8   16  24
            $endFlag = 8 * ($ipKey + 1);//8   16  24  32
            $step[$ipKey] = $newMask > $endFlag ? 1 : ($endFlag - $newMask < 8 ? pow(2, $endFlag - $newMask) : pow(2, 8));
            $decbinItem = str_pad(decbin($item), 8, "0", STR_PAD_LEFT);
            $endIp[] = $mask >= $endFlag ? $item : ($mask > $beginFlag ? bindec(str_pad(substr($decbinItem, 0, $mask - $beginFlag), 8, "1", STR_PAD_RIGHT)) : ($ipKey <= 2 ? pow(2, 8) - 1 : pow(2, 8) - 1));
        }
        //遍历生成网段
        for ($beginIp[0] = $beginIpArray[0]; $beginIp[0] <= $endIp[0]; $beginIp[0] += $step[0]) {
            for ($beginIp[1] = $beginIpArray[1]; $beginIp[1] <= $endIp[1]; $beginIp[1] += $step[1]) {
                for ($beginIp[2] = $beginIpArray[2]; $beginIp[2] <= $endIp[2]; $beginIp[2] += $step[2]) {
                    for ($beginIp[3] = $beginIpArray[3]; $beginIp[3] <= $endIp[3]; $beginIp[3] += $step[3]) {
                        $newSegment = implode('.', $beginIp) . '/' . $newMask;
                        //获取该网段所有的IP
                        $ipArray = getIpBySegment($newSegment);
                        $canUse = true;
                        //判断该网段是否可用
                        if (!empty($usedIpArray)) {
                            foreach ($ipArray as $ip) {
                                if (isset($usedIpArray[$ip])) {
                                    $canUse = false;
                                    break;
                                }
                            }
                        }
                        if ($canUse) {
                            return $newSegment;
                        }
                    }
                }
            }
        }
        return false;
    }
  • 相关阅读:
    rocketmq的broker如何同步信息的?
    SO_LINGER 选项
    哈哈哈
    NAG博客目录
    事后分析$eta$
    项目展示$eta$
    测试报告$eta$
    发布声明$eta$
    Scrum meeting 10
    技术博客6--Django实现列表分页
  • 原文地址:https://www.cnblogs.com/liaokaichang/p/8485202.html
Copyright © 2011-2022 走看看