function ip2cidr($ip_start,$ip_end) {
if(long2ip(ip2long($ip_start))!=$ip_start or long2ip(ip2long($ip_end))!=$ip_end) return NULL; 
$ipl_start=(int)ip2long($ip_start);
$ipl_end=(int)ip2long($ip_end);
if($ipl_start>0 && $ipl_end<0) $delta=($ipl_end+4294967296)-$ipl_start;
else $delta=$ipl_end-$ipl_start;
$netmask=str_pad(decbin($delta),32,"0","STR_PAD_LEFT");
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 NULL;
for($mask=0;$mask<32;$mask++) if($netmask[$mask]==1) break;
if(substr_count($netmask,"0")!=$mask) return NULL;
return "$ip_start/$mask";
}  这个函数不能生成多个cidr

解决方案 »

  1.   

    echo ip2cidr('1.120.0.0', '1.127.255.255'); //1.120.0.0/13function ip2cidr($ip_start,$ip_end) {
      if(long2ip(ip2long($ip_start))!=$ip_start or long2ip(ip2long($ip_end))!=$ip_end) return NULL; 
      $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 = str_pad(decbin($delta), 32, "0", STR_PAD_LEFT);
      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 NULL;
      for($mask=0; $mask<32; $mask++) if($netmask[$mask]==1) break;
      if(substr_count($netmask,"0")!=$mask) return NULL;
      return "$ip_start/$mask";

      

  2.   

    版主大人 您写的和我2楼一样 解决不了1.120.0.0 1.159.255.255 这个IP区间 生成CIDR的问题
      

  3.   

    虽然拆分并不是很困难,但你如何确定拆分点呢?
    比如
    echo ip2cidr('1.120.0.0', '1.127.255.255'); //1.120.0.0/13
    echo ip2cidr('1.128.0.0', '1.159.255.255'); //1.128.0.0/11
    是一种拆法
    echo ip2cidr('1.120.0.0', '1.151.255.255'); //1.120.0.0/11
    echo ip2cidr('1.152.0.0', '1.159.255.255'); //1.152.0.0/13
    又是一种拆法而
    echo ip2cidr('1.120.0.0', '1.159.255.255');
    失败的原因是掩码为
    00000000001001111111111111111111
    其实本身并没有错,只是不能 cidr 表示而已注意到
    echo long2ip(bindec('111111111111111111111')+ip2long('1.120.0.0')); //1.151.255.255
    所以那个第二种拆法是可以机器实现的,而第一种似只能手工实现
      

  4.   

    ip2cidr("1.40.0.0","1.44.255.255");
    00000000000001001111111111111111
    echo long2ip(bindec('111111111111111111111')+ip2long('1.40.0.0')); //1.71.255.255 超出了指定IP的范围
      

  5.   

    结束echo ip2cidr('1.120.0.0', '1.159.255.255'), PHP_EOL;
    echo ip2cidr('1.120.0.0', '1.169.255.255'), PHP_EOL;
    echo ip2cidr('1.120.0.0', '1.179.255.255'), PHP_EOL;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";

    1.120.0.0/13,1.128.0.0/11
    1.120.0.0/15,1.112.0.0/12,1.128.0.0/15,1.128.0.0/13,1.136.0.0/15,1.138.0.0/11
    1.120.0.0/14,1.120.0.0/13,1.128.0.0/14,1.128.0.0/12,1.144.0.0/14,1.148.0.0/11
      

  6.   

    版主大大 小弟不才  您给的那个最终的函数 还是有BUG
    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.254http://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