解决方案 »

  1.   

    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    
      

  2.   

    那可能我之前表述错误了 我的需求就是 用函数实现首IP地址和尾IP地址的区间转化为CIDR格式  这样就可以用来查询某个IP地址是否属于这个CIDR区域,其中检验的方法就是用CIDR再反生成首IP地址和尾IP地址的区间。
    函数功能类似于http://ip2cidr.com 上的
      

  3.   

    其实这是 ip2cidr 的 bug
    函数的原型来自 php 手册,只是增加了分段的功能
    可以看到,分段是在原函数发现做为一段不行的时候进行的
    但由于先天不足,他并没有把你的传入不能作为一段判别出来
      

  4.   

    不知道 这个网站http://ip2cidr.com/  它是怎么实现的  网上的资源好少
      

  5.   

    一篇国外的文章用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;
        }
    }
      

  6.   

    $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
    )
      

  7.   

    还有个更简单的 其中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();     
        } 
    }
      

  8.   

    版主大大 看12楼的 JAVA 函数思路 是否可以优化您的代码 以生成3个CIDR 36.96.0.0/11  36.128.0.0/10 36.192.0.0/11  
    最终让这个函数在PHP沉淀下来 为大家造福
      

  9.   

    $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
    )
    你给的那个链接,最后一节的结果是错的
      

  10.   

    您说的是http://ip2cidr.com/   还是12楼的函数?
      

  11.   

    $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
    )
      

  12.   

    拆的好开呀 版主大大 看看 还能优化下吗
    $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
      

  13.   

    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";
    }
      

  14.   

    $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
            ))
      

  15.   

    $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楼的方法是否合适
      

  16.   

    最终函数:
    $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的函数翻译了