php 进行子网换算(二进制,解决32位/64位系统超出最大int)

2位和64位子网换算,还是跟我之前发布的那个一样的问题,ip转换成int超出了系统最大限制,找了很久终于找到了一种以二进制计算的方式,分享给大家



<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');  
class Subnet extends MY_Controller{      
    public $ip = array();  
    public $mask = array();  
   
    //加载函数  
    function __construct()  
    {  
        parent::__construct();  
    }  
   
    public function index()  
    {  
        $this->load->view('tools/subnet_conversion.html');  
    }   
   
    public function show($ip,$mask){  
        //初始化mask and ip  
        $this->setmask($mask);  
        $this->ip = explode('.', $ip);  
        //计算可用数量通过子网掩码计算总数  
        foreach($this->mask as $k=>$v){  
            $newmask .= $v;  
        }  
        $num = substr_count($newmask,'0');  
        //最大值  
        $data['max'] = pow(2,$num)-2;  
        $data['net'] = $this->net();  
        $data['mask'] = $this->mask() ;  
        $data['range1'] = $data['max'] > 0?$this->onerange():'';  
        $data['range2'] = $data['max'] > 0?$this->endrange():'';  
   
        //最小ip的32位二进制  
        foreach(explode('.',$data['range1']) as $k=>$v){  
            $ip2 = decbin($v);  
            $allip2 .= str_pad($ip2,8,"0",STR_PAD_LEFT);  
        }  
          
        $endallip = $this->binary_plus($allip2, decbin(rand(0,$data['max']-1)));  
        $ip_1 = bindec(substr($endallip,"0",8));  
        $ip_2 = bindec(substr($endallip,"8",8));  
        $ip_3 = bindec(substr($endallip,"16",8));  
        $ip_4 = bindec(substr($endallip,"24",8));  
        $newip = $ip_1.'.'.$ip_2.'.'.$ip_3.'.'.$ip_4;  
        $data['rand'] = $data['max'] > 0?$newip:'-';  
        $data['max'] = $data['max'] > 0?$data['max']:0;  
        echo json_encode($data);  
   
    }  
      
    //初始化mask  
    public function setmask($mask){  
        if (is_numeric($mask)) {  
            //如果参数为数值掩码  
            for ($i = 0; $i < $mask; $i++) {  
                $mask2.='1';  
            }  
            for ($i = $mask; $i < 32; $i++) {  
                $mask2.='0';  
            }  
            $this->mask[] = substr($mask2,"0",8);  
            $this->mask[] = substr($mask2,"8",8);  
            $this->mask[] = substr($mask2,"16",8);  
            $this->mask[] = substr($mask2,'24',8);  
          
        }else {  
            $mask22 = explode('.', $mask);  
            foreach($mask22 as $key=>$val){  
                $Ip = decbin($val);  
                $bIp .= str_pad($Ip,8,"0",STR_PAD_LEFT);  
            }  
            $this->mask[] = substr($bIp,"0",8);  
            $this->mask[] = substr($bIp,"8",8);  
            $this->mask[] = substr($bIp,"16",8);  
            $this->mask[] = substr($bIp,'24',8);  
          
        }  
    }  
      
    //第一个可用地址  
    public function onerange(){  
        for ($i=0;$i<3;$i++){  
            $newone .= $this->startIp($this->ip[$i],$this->mask[$i]);  
            $newone .= '.';  
        }  
        $ip_4 = $this->startIp($this->ip[3],$this->mask[3]);  
       $newone .= ++$ip_4;  
       return $newone;  
    }  
      
      
    //最后一个可用  
    public function endrange(){  
        for($i=0;$i<3;$i++){  
            $newend .= $this->endIp($this->ip[$i],$this->mask[$i]);  
            $newend .= '.';  
        }          
        $ip_4 = $this->endIp($this->ip[3],$this->mask[3]);  
        $newend .= --$ip_4;  
        return $newend;  
    }  
      
    //return 网络地址  
    public function net(){  
        for($i=0;$i<4;$i++){  
            $newnet .= $this->startIp($this->ip[$i],$this->mask[$i]);  
            if($i != 3) $newnet.='.';  
        }  
        return $newnet;  
    }  
      
    //网络地址转换  
    public function startIp($str,$bSub){  
        $bIp = decbin($str);  
        $bIp = str_pad($bIp,8,"0",STR_PAD_LEFT);  
        $sIp = bindec($bIp & $bSub);  
        return $sIp;  
    }  
      
    //结束ip转换  
    public function endIp($str,$bSub){  
        $bIp = decbin($str);  
        $bIp = str_pad($bIp,8,"0",STR_PAD_LEFT);  
        $eIp = bindec($bIp | $this->revBin($bSub));  
        return $eIp;  
    }  
      
    //掩码  
    public function mask(){  
        for ($i=0;$i<4;$i++){  
            $newmask .= bindec($this->mask[$i]);  
            if($i!=3) $newmask .= '.';  
        }  
        return $newmask;  
    }  
      
    public function revBin($s){  
        $p=array('0','1','2');  
        $r=array('2','0','1');  
        return str_replace($p,$r,$s);  
    }  
   
    //二进制加法运算  
    public function binary_plus($binstr1, $binstr2) {  
        $bin_arr1 = str_split($binstr1);  
        $bin_arr2 = str_split($binstr2);  
        $arr_len1 = count($bin_arr1);  
        $arr_len2 = count($bin_arr2);  
        $sum_arr = array();  
        if ($arr_len1 < $arr_len2) {  
            $short_arr = &$bin_arr1;  
        } else {  
            $short_arr = &$bin_arr2;  
        }  
        //将两个数组的长度补到一样长,短数组在前面补0  
        for ($i = 0; $i < abs($arr_len1 - $arr_len2); $i++) {  
            array_unshift($short_arr, 0);  
        }  
        //进位标记  
        $carry = 0;  
        for ($i = count($bin_arr1)-1; $i >= 0; $i--){   
            $result = $bin_arr1[$i] + $bin_arr2[$i] + $carry;  
            switch ($result) {  
                case 0:  
                    array_unshift($sum_arr, 0);  
                    $carry = 0;  
                    break;  
                case 1:  
                    array_unshift($sum_arr, 1);  
                    $carry = 0;  
                    break;  
                case 2:  
                    array_unshift($sum_arr, 0);  
                    $carry = 1;  
                    break;  
                case 3:  
                    array_unshift($sum_arr, 1);  
                    $carry = 1;  
                    break;  
                default:  
                    die();  
            }  
        }  
        if($carry == 1) {  
            array_unshift($sum_arr, 1);  
        }  
        return implode("", $sum_arr);  
    }  
   
}  
   
/* End of file welcome.php */  
/* Location: ./application/controllers/welcome.php */  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值