IpToCidr函数
function ip2cidr($ip_start,$ip_end) { if(long2ip(ip2long($ip_start))!=$ip_start or long2ip(ip2long($ip_end))!=$ip_end) return !trigger_error('ip 不合法', E_USER_NOTICE); $ipl_start = ip2long($ip_start); $ipl_end = ip2long($ip_end); if($ipl_start>0 && $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("区间数量不合法 $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";}
上面是版主大大给写的函数
ip2cidr("36.96.0.0","36.223.255.255")
执行结果36.96.0.0/9
反查
http://www.itmop.com/tool/ipaddress.php
36.96.0.0/9 -> 36.0.0.1 -36.127.255.254 与36.96.0.0 - 36.223.255.255 不一致
有个网站,但是无法看到转换代码
http://ip2cidr.com/
36.96.0.0-36.223.255.255
转化为36.96.0.0/11
36.128.0.0/10
36.192.0.0/11
拆分区间不好掌握。。。
回复讨论(解决方案)
结果结果:可用地址: 8388606掩码: 255.128.0.0网络: 36.96.0.0第一个可用: 36.0.0.1 最后可用: 36.127.255.254 广播: 36.223.255.255
怎么不对啦?
????有??啊。
36.96.0.0/9 -> 36.0.0.1 -36.127.255.254
与36.96.0.0 - 36.223.255.255 不一致
1楼 2楼的 兄弟说完 我以为我手误 结果自己又测试了下 确实ip2cidr("36.96.0.0","36.223.255.255") 执行结果36.96.0.0/9
而36.96.0.0/9 生成IP的区间为 36. 0.0.1 -36. 127.255.254
他那个计算和你的需求是不一样的
他算出的是,在给定的掩码条件下,一个 ip 可以隶属于哪个网段
需求不同,结果也不同
那可能我之前表述错误了 我的需求就是 用函数实现首IP地址和尾IP地址的区间转化为CIDR格式 这样就可以用来查询某个IP地址是否属于这个CIDR区域,其中检验的方法就是用CIDR再反生成首IP地址和尾IP地址的区间。
函数功能类似于http://ip2cidr.com 上的
其实这是 ip2cidr 的 bug
函数的原型来自 php 手册,只是增加了分段的功能
可以看到,分段是在原函数发现做为一段不行的时候进行的
但由于先天不足,他并没有把你的传入不能作为一段判别出来
不知道 这个网站http://ip2cidr.com/ 它是怎么实现的 网上的资源好少
一篇国外的文章用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<String> rangeToCidrList(String istart, String iend) { int start = toInteger(istart); int end = toInteger(iend); List<String> result = new ArrayList<String>(); 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.255.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 不合法', 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)
还有个更简单的 其中2个函数PHP都有库函数 实测也可以
import java.util.ArrayList;import java.util.List;public class RangeToCidr { public static List<String> range2cidrlist( String startIp, String endIp ) { long start = ipToLong(startIp); long end = ipToLong(endIp); ArrayList<String> pairs = new ArrayList<String>(); 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(); } }
版主大大 看12楼的 JAVA 函数思路 是否可以优化您的代码 以生成3个CIDR 36.96.0.0/11 36.128.0.0/10 36.192.0.0/11
最终让这个函数在PHP沉淀下来 为大家造福
$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)
你给的那个链接,最后一节的结果是错的
您说的是http://ip2cidr.com/ 还是12楼的函数?
确实 36.128.0.0/9 已经超出了36.223.255.255
$r = ip2cidr("36.96.0.0","36.223.255.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 不合法', 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)
我试试不同的IP地址段 做个测试
拆的好开呀。。。 版主大大 看看 还能优化下吗
$ip_st = "103.233.183.0";$ip_end = "103.233.183.255";print $ip_st."-".$ip_end."<br>";$cidr_arr = ip2cidr($ip_st,$ip_end );print_r($cidr_arr);print "<br>";for($i = 0 ; $i < count($cidr_arr); $i++){ print $cidr_arr[$i]." : "; print cidr_conv($cidr_arr[$i])."<br>"; }
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.224/28 [4] => 103.233.183.240/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.224/28 : 103.233.183.224 - 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.251
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 不合法', 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] => 524286
[start] => 210.80.0.1
[end] => 210.87.255.254
[broadcast] => 210.87.255.255
)
)
这块就存在BUG了 您看下12楼的方法是否合适
最终函数:
$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; }
谢谢版主大大的悉心指导,最后还是将JAVA的函数翻译了

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Go語言提供了兩種動態函數創建技術:closures和反射。 closures允許存取閉包作用域內的變量,而反射可使用FuncOf函數建立新函數。這些技術在自訂HTTP路由器、實現高度可自訂的系統和建置可插拔的元件方面非常有用。

在C++函數命名中,考慮參數順序至關重要,可提高可讀性、減少錯誤並促進重構。常見的參數順序約定包括:動作-物件、物件-動作、語意意義和遵循標準函式庫。最佳順序取決於函數目的、參數類型、潛在混淆和語言慣例。

1. SUM函數,用於對一列或一組單元格中的數字進行求和,例如:=SUM(A1:J10)。 2、AVERAGE函數,用於計算一列或一組儲存格中的數字的平均值,例如:=AVERAGE(A1:A10)。 3.COUNT函數,用於計算一列或一組單元格中的數字或文字的數量,例如:=COUNT(A1:A10)4、IF函數,用於根據指定的條件進行邏輯判斷,並返回相應的結果。

C++函數中預設參數的優點包括簡化呼叫、增強可讀性、避免錯誤。缺點是限制靈活性、命名限制。可變參數的優點包括無限彈性、動態綁定。缺點包括複雜性更高、隱式型別轉換、除錯困難。

C++中的函數傳回參考類型的好處包括:效能提升:引用傳遞避免了物件複製,從而節省了記憶體和時間。直接修改:呼叫方可以直接修改傳回的參考對象,而無需重新賦值。程式碼簡潔:引用傳遞簡化了程式碼,無需額外的賦值操作。

C++中的異常處理可透過自訂異常類別增強,提供特定錯誤訊息、上下文資訊以及根據錯誤類型執行自訂操作。定義繼承自std::exception的異常類,提供特定的錯誤訊息。使用throw關鍵字拋出自訂異常。在try-catch區塊中使用dynamic_cast將捕獲到的異常轉換為自訂異常類型。在實戰案例中,open_file函數會拋出FileNotFoundException異常,捕捉並處理該異常可提供更具體的錯誤訊息。

自訂PHP函數與預定義函數的差異在於:作用域:自訂函數僅限於其定義範圍,而預定義函數可在整個腳本中存取。定義方式:自訂函數使用function關鍵字定義,而預先定義函數則由PHP核心定義。參數傳遞:自訂函數接收參數,而預先定義函數可能不需要參數。擴充性:自訂函數可以根據需要創建,而預定義函數是內建的且無法修改。
