IpToCidr function
Function ip2cidr ($ ip_start, $ ip_end) {if (long2ip (ip2long ($ ip_start ))! = $ Ip_start or long2ip (ip2long ($ ip_end ))! = $ Ip_end) return! Trigger_error ('IP illegal ', E_USER_NOTICE); $ ipl_start = ip2long ($ ip_start); $ ipl_end = ip2long ($ ip_end ); if ($ ipl_start> 0 & amp; $ ipl_end <0) $ delta = ($ ipl_end + 4294967296)-$ ipl_start; else $ delta = $ ipl_end-$ ipl_start; $ netmask = sprintf ('% 032b', $ delta); if (ip2long ($ ip_start) = 0 & substr_count ($ netmask, "1") = 32) return "0.0.0.0/0"; if ($ delta <0 or ($ delta> 0 & $ delta % 2 = 0) return! Trigger_error ("The number of intervals is invalid $ delta", E_USER_NOTICE); for ($ mask = 0; $ mask <32; $ mask ++) if ($ netmask [$ mask] = 1) break; if (substr_count ($ netmask, "0 ")! = $ Mask) {$ w = strrpos ($ netmask, '0') + 1; $ m = pow (2, 32-$ w)-1; $ ip_start = long2ip ($ ipl_start &~ $ M) + $ m + 1); return long2ip ($ ipl_start &~ $ M). "/$ w,". ip2cidr ($ ip_start, $ ip_end) ;}; return "$ ip_start/$ mask ";}
The above is the function that the moderator writes.
Ip2cidr ("36.96.0.0", "36.223.255.255 ")
Execution result 36.96.0.0/9
Reverse lookup
Http://www.itmop.com/tool/ipaddress.php
36.96.0.0/9-> 36.0.0.1-36.127.255.254 is inconsistent with 36.96.0.0-36.223.255.255
There is a website, but you cannot see the conversion code
Http://ip2cidr.com/
36.96.0.0-36.223.255.255
Convert to 36.96.0.0/11
36.128.0.0/10
36.192.0.0/11
The split interval is hard to grasp...
Reply to discussion (solution)
Result: available address: 8388606 mask: 255.128.0.0 network: 36.96.0.0 first available: 36.0.0.1 last available: 36.127.255.254 broadcast: 36.223.255.255
Why not?
???? Yes ?? Ah.
36.96.0.0/9-> 36.0.0.1-36.127.255.254
Inconsistent with 36.96.0.0-36.223.255.255
After my brother on the second floor on the first floor said, I thought I had to test ip2cidr ("36.96.0.0", "36.223.425255") again by mistake. the execution result is 36.96.0.0/9.
The IP generation range of 36.96.0.0/9 is 36. 0.0.1-36. 127.255.254.
His computing is different from your needs.
It calculates which network segment an ip address can belong to under a given mask.
Different requirements and different results
It may have been wrong. my requirement is to use the function to convert the ranges of the first IP address and the last IP address to the CIDR format so that I can query whether an IP address belongs to this CIDR region, the test method is to use CIDR to generate the interval between the first IP address and the last IP address.
Function functions are similar to
This is actually a bug in ip2cidr.
The function prototype is from the php manual, but the segmentation function is added.
We can see that the segmentation is performed when the original function finds that the segment cannot work.
However, due to inherent deficiency, he did not identify your input as a segment.
I don't know how this website http://ip2cidr.com/how it is achieved on the Internet with fewer resources
A foreign article is implemented in JAVA
import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;public class RangeToCidr { private static final String IP_ADDRESS = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})"; private static final Pattern addressPattern = Pattern.compile(IP_ADDRESS); public static List
rangeToCidrList(String istart, String iend) { int start = toInteger(istart); int end = toInteger(iend); List
result = new ArrayList
(); while (end >= start) { int maxsize = imaxblock( start, 32); double x = (Math.log(end - start + 1) / Math.log(2) ) ; int maxdiff = (int) (Math.floor(32 - Math.floor(x))); String ip = intToIP(start); if (maxsize < maxdiff) { maxsize = maxdiff; } result.add( ip + "/" + (int)maxsize ); start += Math.pow(2, (32-maxsize)); } return result; } private static int toInteger(String address) { Matcher matcher = addressPattern.matcher(address); if (matcher.matches()) { return matchAddress(matcher); } else throw new IllegalArgumentException("Could not parse [" + address + "]"); } private static int matchAddress(Matcher matcher) { int addr = 0; for (int i = 1; i <= 4; ++i) { int n = (rangeCheck(Integer.parseInt(matcher.group(i)), -1, 255)); addr |= ((n & 0xff) << 8*(4-i)); } return addr; } private static int rangeCheck(int value, int begin, int end) { if (value > begin && value <= end) // (begin,end] return value; throw new IllegalArgumentException("Value [" + value + "] not in range ("+begin+","+end+"]"); } private static String intToIP(int val) { int octets[] = new int[4]; for (int j = 3; j >= 0; --j) octets[j] |= ((val >>> 8*(3-j)) & (0xff)); StringBuilder str = new StringBuilder(); for (int i =0; i < octets.length; ++i){ str.append(octets[i]); if (i != octets.length - 1) { str.append("."); } } return str.toString(); } private static long imask(int t) { return (long)(Math.pow(2, 32) - Math.pow(2, 32-t) ) ; } private static int imaxblock(long ibase, int tbit) { while (tbit > 0) { long im = imask(tbit-1); long imand = ibase & im ; if (imand != ibase) { break; } tbit--; } return tbit; }}
$ R = ip2cidr ("36.96.0.1", "36.223.0000255"); print_r ($ r); function ip2cidr ($ ip_start, $ ip_end) {$ res = array (); if (long2ip (ip2long ($ ip_start ))! = $ Ip_start or long2ip (ip2long ($ ip_end ))! = $ Ip_end) return! Trigger_error ('IP illegal ', E_USER_NOTICE); $ ipl_start = ip2long ($ ip_start); if ($ ipl_start <0) $ ipl_start + = 0x100000000; $ ipl_end = ip2long ($ ip_end); if ($ ipl_end <0) $ ipl_end + = 0x100000000; $ ipl = $ ipl_start; do {$ k = strrpos (sprintf ('% 032b', $ ipl), '1'); $ cidr = $ k + 1; $ dk = pow (2, 32-$ K-1); $ mask = $ dk-1; $ res [] = sprintf ("% s/% d", long2ip ($ ipl &~ $ Mask), $ cidr); $ ipl + = $ dk;} while ($ ipl <$ ipl_end); return $ res ;}
Array( [0] => 36.96.0.1/32 [1] => 36.96.0.2/31 [2] => 36.96.0.4/30 [3] => 36.96.0.8/29 [4] => 36.96.0.16/28 [5] => 36.96.0.32/27 [6] => 36.96.0.64/26 [7] => 36.96.0.128/25 [8] => 36.96.1.0/24 [9] => 36.96.2.0/23 [10] => 36.96.4.0/22 [11] => 36.96.8.0/21 [12] => 36.96.16.0/20 [13] => 36.96.32.0/19 [14] => 36.96.64.0/18 [15] => 36.96.128.0/17 [16] => 36.97.0.0/16 [17] => 36.98.0.0/15 [18] => 36.100.0.0/14 [19] => 36.104.0.0/13 [20] => 36.112.0.0/12 [21] => 36.128.0.0/9)
There is also a simpler one. Two of the functions in PHP both have library function tests.
import java.util.ArrayList;import java.util.List;public class RangeToCidr { public static List
range2cidrlist( String startIp, String endIp ) { long start = ipToLong(startIp); long end = ipToLong(endIp); ArrayList
pairs = new ArrayList
(); while ( end >= start ) { byte maxsize = 32; while ( maxsize > 0) { long mask = CIDR2MASK[ maxsize -1 ]; long maskedBase = start & mask; if ( maskedBase != start ) { break; } maxsize--; } double x = Math.log( end - start + 1) / Math.log( 2 ); byte maxdiff = (byte)( 32 - Math.floor( x ) ); if ( maxsize < maxdiff) { maxsize = maxdiff; } String ip = longToIP(start); pairs.add( ip + "/" + maxsize); start += Math.pow( 2, (32 - maxsize) ); } return pairs; } public static final int[] CIDR2MASK = new int[] { 0x00000000, 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF }; private static long ipToLong(String strIP) { long[] ip = new long[4]; String[] ipSec = strIP.split("\\."); for (int k = 0; k < 4; k++) { ip[k] = Long.valueOf(ipSec[k]); } return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3]; } private static String longToIP(long longIP) { StringBuffer sb = new StringBuffer(""); sb.append(String.valueOf(longIP >>> 24)); sb.append("."); sb.append(String.valueOf((longIP & 0x00FFFFFF) >>> 16)); sb.append("."); sb.append(String.valueOf((longIP & 0x0000FFFF) >>> 8)); sb.append("."); sb.append(String.valueOf(longIP & 0x000000FF)); return sb.toString(); } }
The moderator can check whether the JAVA function idea on the 12th floor can optimize your code to generate three CIDR 36.96.0.0/11 36.128.0.0/10 36.192.0.0/11
Finally, let this function accumulate in PHP for the benefit of everyone.
$r = ip2cidr("36.96.0.0","36.223.255.255");print_r($r);
Array( [0] => 36.96.0.0/11 [1] => 36.128.0.0/9)
The link you gave is incorrect in the last section.
Are you talking about the http://ip2cidr.com/or the function on the 12th floor?
Indeed, 36.128.0.0/9 has exceeded 36.223.255.255.
$ R = ip2cidr ("36.96.0.0", "36.223.425255"); print_r ($ r); function ip2cidr ($ ip_start, $ ip_end) {$ res = array (); if (long2ip (ip2long ($ ip_start ))! = $ Ip_start or long2ip (ip2long ($ ip_end ))! = $ Ip_end) return! Trigger_error ('IP illegal ', E_USER_NOTICE); $ ipl_start = ip2long ($ ip_start); if ($ ipl_start <0) $ ipl_start + = 0x100000000; $ ipl_end = ip2long ($ ip_end); if ($ ipl_end <0) $ ipl_end + = 0x100000000; $ ipl = $ ipl_start; do {$ k = strrpos (sprintf ('% 032b', $ ipl), '1'); $ cidr = $ k + 1; $ dk = pow (2, 32-$ K-1); if ($ ipl + $ dk> $ ipl_end) {$ dk/= 2; $ cidr ++ ;}$ mask = $ dk-1; $ res [] = sprintf ("% s/% d", long2ip ($ ipl &~ $ Mask), $ cidr); $ ipl + = $ dk;} while ($ ipl <$ ipl_end); return $ res ;}
Array( [0] => 36.96.0.0/11 [1] => 36.128.0.0/10 [2] => 36.192.0.0/11)
I will try to test different IP address segments.
It's easy to split... Can the moderator be optimized?
$ip_st = "103.233.183.0";$ip_end = "103.233.183.255";print $ip_st."-".$ip_end."
";$cidr_arr = ip2cidr($ip_st,$ip_end );print_r($cidr_arr);print "
";for($i = 0 ; $i < count($cidr_arr); $i++){print $cidr_arr[$i]." : ";print cidr_conv($cidr_arr[$i])."
";}
103.233.183.0-103.233.183.255
Array ([0] => 103.233.183.0/25 [1] => 103.233.183.128/26 [2] => 103.233.183.192/27 [3] => 103.233.183.small/28 [4] => Large /29 [5] => 103.233.183.248/30 [6] => 103.233.183.252/31 [7] => 103.233.183.254/32)
103.233.183.0/25: 103.233.183.0-103.233.183.127
103.233.183.128/26: 103.233.183.128-103.233.183.191
103.233.183.192/27: 103.233.183.192-103.233.183.223
103.233.183.small/28: 103.233.183.small-103.233.183.239
103.233.183.240/29: 103.233.183.240-103.233.183.247
103.233.183.248/30: 103.233.183.248-103.233.183.small
103.233.183.252/31: 103.233.183.252-103.233.183.253
103.233.183.254/32: 103.233.183.254-103.233.183.254
function cidr_conv($cidr_address) { $first = substr($cidr_address, 0, strpos($cidr_address, "/")); $netmask = substr(strstr($cidr_address, "/"), 1); $first_bin = str_pad(decbin(ip2long($first)), 32, "0", STR_PAD_LEFT); $netmask_bin = str_pad(str_repeat("1", (integer)$netmask), 32, "0", STR_PAD_RIGHT); for ($i = 0; $i < 32; $i++) { if ($netmask_bin[$i] == "1") $last_bin .= $first_bin[$i]; else $last_bin .= "1"; } $last = long2ip(bindec($last_bin)); return "$first - $last";}
$ R = ip2cidr ("103.233.183.0", "103.233.183.255"); print_r ($ r); function ip2cidr ($ ip_start, $ ip_end) {$ res = array (); if (long2ip (ip2long ($ ip_start ))! = $ Ip_start or long2ip (ip2long ($ ip_end ))! = $ Ip_end) return! Trigger_error ('IP illegal ', E_USER_NOTICE); $ ipl_start = ip2long ($ ip_start); if ($ ipl_start <0) $ ipl_start + = 0x100000000; $ ipl_end = ip2long ($ ip_end); if ($ ipl_end <0) $ ipl_end + = 0x100000000; $ ipl = $ ipl_start; do {$ k = strrpos (sprintf ('% 032b', $ ipl), '1'); $ cidr = $ k + 1; $ dk = pow (2, 32-$ K-1); if ($ ipl + $ dk> $ ipl_end + 1) {$ dk/= 2; $ cidr ++;} $ mask = $ dk-1; $ res [] = array ('cidr' => sprintf ("% s/% D ", long2ip ($ ipl &~ $ Mask), $ cidr), 'mask' => long2ip (~ $ Mask), 'net' => long2ip ($ ipl &~ $ Mask), 'usable' => $ mask-1, 'Start' => long2ip ($ ipl &~ $ Mask) + 1), 'end' => long2ip ($ ipl | $ mask)-1 ), 'broadcast' => long2ip ($ ipl | $ mask),); $ ipl + = $ dk;} while ($ ipl <$ ipl_end); return $ res ;}
Array( [0] => Array ( [cidr] => 103.233.183.0/24 [mask] => 255.255.255.0 [net] => 103.233.183.0 [usable] => 254 [start] => 103.233.183.1 [end] => 103.233.183.254 [broadcast] => 103.233.183.255 ))
$ R = ip2cidr ("210.80.0.0", "210.80.63.255 ");
Print_r ($ r );
Array
(
[0] => Array
(
[Cidr] => 210.80.0.0/13
[Mask] => 255.248.0.0
[Net] => 210.80.0.0
[Usable] = & gt; 524286
[Start] => 210.80.0.1
[End] => 210.87.255.254
[Broadcast] => 210.87.255.255
)
)
This is a BUG. check whether the method on the 12th floor is suitable.
Final function:
$CIDR2MASK = array( 0x00000000, 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF ); function ipTocidr($ip_start,$ip_end) { global $CIDR2MASK; $StartIp = ip2long($ip_start); $EndIp = ip2long($ip_end); $pairs = array(); while ( $EndIp >= $StartIp ) { $maxsize = 32; while ( $maxsize > 0) { $mask = $CIDR2MASK[$maxsize-1]; $maskedBase = $StartIp & $mask ; if ( $maskedBase != $StartIp ) { break; } $maxsize--; } $x = log( $EndIp - $StartIp + 1) / log(2); $maxdiff = 32 - floor($x) ; if ( $maxsize < $maxdiff) { $maxsize = $maxdiff; } $ip = long2ip($StartIp); $pairs[] = $ip."/".$maxsize; $StartIp += pow( 2, (32 - $maxsize) ); } return $pairs; }
Thank you for your great guidance. at last, I translated the JAVA function.