php 进行子网换算(二进制,解决32位/64位系统超出最大int)
2016-06-24 17:39
495 查看
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 */
<?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 */
相关文章推荐
- 一个关于if else容易迷惑的问题
- PHP5.2.*防止Hash冲突拒绝服务攻击的Patch
- 深入理解PHP之匿名函数
- JSP/PHP基于Ajax的分页功能实现
- 关于PHP通过PDO用中文条件查询MySQL的问题。
- 什么是设计模式
- PHP数据库长连接mysql_pconnect的细节
- Php Installing An Expansion
- rem : web app适配的秘密武器
- jquery高级应用之Deferred对象
- php7 读取php.ini[4]
- PHP+Apache在Windows 9x下的安装和配置
- IIS 6 的 PHP 最佳配置方法
- 安装Apache和PHP的一些补充
- Linux Apache+MySQL+PHP
- 建立Apache+PHP+MySQL数据库驱动的动态网站
- PHP 5.3.0 安装分析心得
- apache 环境下 php 的配置注意事项
- 简单好用的PHP分页类