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的函数翻译了

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Bahasa Go menyediakan dua teknologi penciptaan fungsi dinamik: penutupan dan refleksi. penutupan membenarkan akses kepada pembolehubah dalam skop penutupan, dan refleksi boleh mencipta fungsi baharu menggunakan fungsi FuncOf. Teknologi ini berguna dalam menyesuaikan penghala HTTP, melaksanakan sistem yang sangat boleh disesuaikan dan membina komponen boleh pasang.

Dalam penamaan fungsi C++, adalah penting untuk mempertimbangkan susunan parameter untuk meningkatkan kebolehbacaan, mengurangkan ralat dan memudahkan pemfaktoran semula. Konvensyen susunan parameter biasa termasuk: tindakan-objek, objek-tindakan, makna semantik dan pematuhan perpustakaan standard. Susunan optimum bergantung pada tujuan fungsi, jenis parameter, kemungkinan kekeliruan dan konvensyen bahasa.

Kunci untuk menulis fungsi Java yang cekap dan boleh diselenggara ialah: pastikan ia mudah. Gunakan penamaan yang bermakna. Mengendalikan situasi khas. Gunakan keterlihatan yang sesuai.

1. Fungsi SUM digunakan untuk menjumlahkan nombor dalam lajur atau sekumpulan sel, contohnya: =SUM(A1:J10). 2. Fungsi AVERAGE digunakan untuk mengira purata nombor dalam lajur atau sekumpulan sel, contohnya: =AVERAGE(A1:A10). 3. Fungsi COUNT, digunakan untuk mengira bilangan nombor atau teks dalam lajur atau sekumpulan sel, contohnya: =COUNT(A1:A10) 4. Fungsi IF, digunakan untuk membuat pertimbangan logik berdasarkan syarat yang ditentukan dan mengembalikan hasil yang sepadan.

Kelebihan parameter lalai dalam fungsi C++ termasuk memudahkan panggilan, meningkatkan kebolehbacaan dan mengelakkan ralat. Kelemahannya ialah fleksibiliti terhad dan sekatan penamaan. Kelebihan parameter variadic termasuk fleksibiliti tanpa had dan pengikatan dinamik. Kelemahan termasuk kerumitan yang lebih besar, penukaran jenis tersirat dan kesukaran dalam penyahpepijatan.

Faedah fungsi mengembalikan jenis rujukan dalam C++ termasuk: Peningkatan prestasi: Melewati rujukan mengelakkan penyalinan objek, sekali gus menjimatkan memori dan masa. Pengubahsuaian langsung: Pemanggil boleh mengubah suai secara langsung objek rujukan yang dikembalikan tanpa menugaskannya semula. Kesederhanaan kod: Lulus melalui rujukan memudahkan kod dan tidak memerlukan operasi penugasan tambahan.

Perbezaan antara fungsi PHP tersuai dan fungsi yang dipratentukan ialah: Skop: Fungsi tersuai terhad kepada skop definisinya, manakala fungsi yang dipratentukan boleh diakses di seluruh skrip. Cara mentakrifkan: Fungsi tersuai ditakrifkan menggunakan kata kunci fungsi, manakala fungsi yang dipratakrifkan ditakrifkan oleh kernel PHP. Lulus parameter: Fungsi tersuai menerima parameter, manakala fungsi yang dipratentukan mungkin tidak memerlukan parameter. Kebolehlanjutan: Fungsi tersuai boleh dibuat mengikut keperluan, manakala fungsi yang dipratentukan terbina dalam dan tidak boleh diubah suai.

Parameter rujukan dalam fungsi C++ (pada asasnya alias berubah-ubah, mengubah suai rujukan mengubah suai pembolehubah asal) dan parameter penunjuk (menyimpan alamat memori pembolehubah asal, mengubah suai pembolehubah dengan menyahrujuk penunjuk) mempunyai penggunaan yang berbeza apabila menghantar dan mengubah suai pembolehubah. Parameter rujukan sering digunakan untuk mengubah suai pembolehubah asal (terutamanya struktur besar) untuk mengelakkan overhed salinan apabila diserahkan kepada pembina atau pengendali tugasan. Parameter penunjuk digunakan untuk secara fleksibel menunjuk ke lokasi memori, melaksanakan struktur data dinamik, atau menghantar penunjuk nol untuk mewakili parameter pilihan.
