由于最近业务需要,写了个获取网段内所有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;}
php计算网段内所有IP,分配子网段
原文地址:https://www.cnblogs.com/liaokaichang/p/8485202.html