我在这个网站上看到了各种各样的问题和答案,我仍然很难解决这个问题(可能是因为我感冒了)。无论如何,我正在努力想出一个小型的网络应用程序,它将为我们的每个办公室创建IP地址表。
就像说如果我为10.1.10.0/4创建一个新的范围,它将创建一个数组(我可以打印到表格中):
10.1.10.0 network ID
10.1.10.1 gateway
10.1.10.2 usable
10.1.10.3 broadcast
(并不是说它会自动插入描述,但这就是我们要做的事情。)
我很确定我将使用ip2long / long2ip将地址存储为整数但仍然存在。
答案 0 :(得分:11)
正如您已经注意到的,所有IPv4地址都可以使用ip2long()
转换为数字,并使用long2ip()
转换回来。关键的额外位我不确定你注意到顺序IP与顺序数字相对应,所以你可以操纵这些数字!
给定CIDR前缀(例如,您的范围为$prefix = 30
),您可以使用bit shift operator计算该范围内的IP数量:
$ip_count = 1 << (32 - $prefix);
然后使用以下方法遍历该范围内的所有IP:
$start = ip2long($start_ip);
for ($i = 0; $i < $ip_count; $i++) {
$ip = long2ip($start + $i);
// do stuff with $ip...
}
答案 1 :(得分:4)
我正在使用以下功能为我提供网络,第一个可用的,最后一个可用的以及广播地址以及所有主机:
function ipv4Breakout ($ip_address, $ip_nmask) {
$hosts = array();
//convert ip addresses to long form
$ip_address_long = ip2long($ip_address);
$ip_nmask_long = ip2long($ip_nmask);
//caculate network address
$ip_net = $ip_address_long & $ip_nmask_long;
//caculate first usable address
$ip_host_first = ((~$ip_nmask_long) & $ip_address_long);
$ip_first = ($ip_address_long ^ $ip_host_first) + 1;
//caculate last usable address
$ip_broadcast_invert = ~$ip_nmask_long;
$ip_last = ($ip_address_long | $ip_broadcast_invert) - 1;
//caculate broadcast address
$ip_broadcast = $ip_address_long | $ip_broadcast_invert;
foreach (range($ip_first, $ip_last) as $ip) {
array_push($hosts, $ip);
}
$block_info = array(array("network" => "$ip_net"),
array("first_host" => "$ip_first"),
array("last_host" => "$ip_last"),
array("broadcast" => "$ip_broadcast"),
$hosts);
return $block_info;
}
我还注意到你要求根据CIDR表示法进行计算。这是我用来将CIDR转换为点分十进制的函数:
function v4CIDRtoMask($cidr) {
$cidr = explode('/', $cidr);
return array($cidr[0], long2ip(-1 << (32 - (int)$cidr[1])));
}
我主要处理点分十进制而不是CIDR表示法。 ipv4Breakout函数返回一个多维数组,其中包含您需要的所有长格式信息。如果需要实际的点分十进制IP地址,则需要使用long2ip()。该功能需要通过点分十进制格式的IP地址和子网掩码。
希望这可以帮助你或其他任何人。
答案 2 :(得分:1)
我的版本可以帮助您使用变量。
<?php
$ip_address = "192.168.0.2";
$ip_nmask = "255.255.255.0";
ipv4Breakout($ip_address, $ip_nmask);
function ipv4Breakout ($ip_address, $ip_nmask) {
//convert ip addresses to long form
$ip_address_long = ip2long($ip_address);
$ip_nmask_long = ip2long($ip_nmask);
//caculate network address
$ip_net = $ip_address_long & $ip_nmask_long;
//caculate first usable address
$ip_host_first = ((~$ip_nmask_long) & $ip_address_long);
$ip_first = ($ip_address_long ^ $ip_host_first) + 1;
//caculate last usable address
$ip_broadcast_invert = ~$ip_nmask_long;
$ip_last = ($ip_address_long | $ip_broadcast_invert) - 1;
//caculate broadcast address
$ip_broadcast = $ip_address_long | $ip_broadcast_invert;
//Output
$ip_net_short = long2ip($ip_net);
$ip_first_short = long2ip($ip_first);
$ip_last_short = long2ip($ip_last);
$ip_broadcast_short = long2ip($ip_broadcast);
echo "Network - " . $ip_net_short . "<br>";
echo "First usable - " . $ip_first_short . "<br>";
echo "Last usable - " . $ip_last_short . "<br>";
echo "Broadcast - " . $ip_broadcast_short . "<br>";
}
答案 3 :(得分:0)
这是基于CIDR计算真实IP范围的实际方法:
最高答案实际上是不正确的。它给出了错误的IP范围列表。
function ipRange($cidr) {
$range = array();
$cidr = explode('/', $cidr);
$range[0] = long2ip((ip2long($cidr[0])) & ((-1 << (32 - (int)$cidr[1]))));
$range[1] = long2ip((ip2long($range[0])) + pow(2, (32 - (int)$cidr[1])) - 1);
return $range;
}
var_dump(ipRange("207.64.1.68/28"));
//////////////////OUTPUT////////////////////////
// array(2) {
// [0]=>
// string(12) "207.64.1.64"
// [1]=>
// string(12) "207.64.1.79"
// }
/////////////////////////////////////////////////
IP:207.64.1.68
应该给我207.64.1.64和207.64.1.79之间的所有IP
其他答案不减去,它们仅从207.64.1.68-207.64.1.83(在IP范围块中不正确)中得出
您可以在此处进行检查:https://www.ipaddressguide.com/cidr
答案 4 :(得分:0)
我创建了这个php函数,以获取网络/范围的子网划分。它适用于ipv4或ipv6。
如果php <5.4,请使用此hex2bin函数https://github.com/dompdf/dompdf/issues/1692
function divide_ip_range($cidr="2001:db8:abc:12ff::/54",$mindivs=2){ // input range 192.168.4.0/24 and returns array with the 1st range and 2nd range [0] => 192.168.4.0/25 , [1] => 192.168.4.127/25
$outarr=array();
list($ipaddr,$range) = explode('/', $cidr);
for($rngsplit=1;pow(2,$rngsplit)<$mindivs;$rngsplit++){} // find to how many networks to divide
$divs=pow(2,$rngsplit);
$divcidr=(int)$range+$rngsplit;
if(preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/",$ipaddr)){ // IPv4
$ip_address_long = ip2long($ipaddr);
$ip_nmask_long=(-1 << (32 - $range));
$ip_net = $ip_address_long & $ip_nmask_long;
$ip_broadcast_invert = ~$ip_nmask_long;
$ip_last = ($ip_address_long | $ip_broadcast_invert) - 1;
$ip_broadcast = $ip_address_long | $ip_broadcast_invert;
$numofhosts=pow(2,32-$range)-2;
for ($i=0;$i<$divs;$i++){
$outarr[]=long2ip($ip_net+$i*ceil($numofhosts/$divs)+($i*ceil($numofhosts/$divs)%2) )."/$divcidr";
}
//echo "Net:$ipaddr/$range\nFirst:".long2ip($ip_net)."\nLast: ".long2ip($ip_last)."\nNumOfHosts:$numofhosts \n";
} else if (preg_match("/^[0-9a-f:]+$/",$ipaddr)) { // IPv6 section
$ip_addr_bin = inet_pton($ipaddr);
$ip_addr_hex = bin2hex($ip_addr_bin);
$flexbits = 128 - $range; // Calculate the number of 'flexible' bits for first net
$pos = 31; $addr_hex_first = $ip_addr_hex; $addr_hex_last = $ip_addr_hex;
while ($flexbits > 0) {
$orig_val = hexdec(substr($ip_addr_hex, $pos, 1)); // dec value of pos char. ex. f=15
$mask = 0xf << (min(4,$flexbits)); // calculate the subnet mask. min() prevents comparison to be negative
$new_val_first = $orig_val & $mask;
$addr_hex_first = substr_replace($addr_hex_first, dechex($new_val_first) , $pos, 1); // Put hex character in pos
$segmask=(pow(2,min(4,$flexbits))-1); // Last address: OR it with (2^flexbits)-1, with flexbits limited to 4 at a time
$new_val_last = $orig_val | $segmask;
$addr_hex_last = substr_replace($addr_hex_last, dechex($new_val_last) , $pos, 1);
$pos--; $flexbits -= 4; // Next nibble
}
$partpos=(4*floor($pos/4)); // The 4 digits that vary by the subnetting
$partfirst=substr($addr_hex_first,$partpos,4);
$partlast=substr($addr_hex_last,$partpos,4);
$numofhosts=(hexdec($partlast)+1-hexdec($partfirst));
for ($i=0;$i<$divs;$i++){
$partdiv=dechex(hexdec($partfirst)+$i*$numofhosts/$divs);
$addr_hex_div=substr_replace($addr_hex_first, $partdiv , $partpos, 4);
$outarr[]=inet_ntop(hex2bin($addr_hex_div))."/$divcidr";
}
//echo "Net:$ipaddr/$range\nFirst:".inet_ntop(hex2bin($addr_hex_first))."\nLast:".inet_ntop(hex2bin($addr_hex_last))."\nNumOfHosts:$numofhosts\nDivide at partpos:$partpos ($partlast+1-$partfirst)/$divs=$partdiv\n";
}
return $outarr;
}