PHP中IP地址与整型数字互相转换详解


Posted in PHP onAugust 20, 2014

IP转换成整型存储是数据库优化一大趋势,不少人目前存储IP时还在使用字符串类型存储,字符串索引比整型索引消耗资源很多,特别是表中数据量大的时候,以及求查询某一个ip段的数据,今天说的ip是指ip4,ip6不在本文范围内。

系统函数ip2long与long2ip
PHP中有内置函数ip2long可以将ip地址转换整型。

$ip = '210.110.11.49';

echo ip2long($ip);

输出:
-764540111

输出的整型有负号是因为我们得到的结果是有符号整型,有符号整型最大值2147483647,要把结果转换为无符号型可以这么写:
3530427185

使用long2ip把整型转换回ip地址

$ip = '210.110.11.49';

$ip_int = ip2long($ip);

echo $ip."<br />";

echo $ip_int."<br />";

echo long2ip($ip_int);

输出:
210.110.11.49

-764540111

210.110.11.49

从结果可以看到,ip与整型可以通过函数完成。

系统函数小bug

这中bug网上一搜都是,大意说的是ip某段加个前导0,先来看看这个bug实例

$ip = '210.110.011.49';

$ip_int = ip2long($ip);

echo $ip."<br />";

echo $ip_int."<br />";

echo long2ip($ip_int);

输出:
210.110.011.49

-764540623

210.110.9.49

转换结果不匹配,我们试着在ip第一段数字前加前导0,再看看

$ip = '021.110.11.49';

$ip_int = ip2long($ip);

echo $ip."<br />";

echo $ip_int."<br />";

echo long2ip($ip_int);

输出:
021.110.11.49

292424497

17.110.11.49

转换结果都出错。以上例子都是因为加了前导0后导致转换结果出错,连带逆转结果与原转换ip不匹配。

转换原理

目前有两个算法:
第一、第一段乘以256的三次方,第二段乘以256的平方,第三段乘以256、最后总和

$ip = '0210.110.11.49';

 

function ipToInt($ip){

    $iparr = explode('.',$ip);

    $num = 0;

    for($i=0;$i<count($iparr);$i++){

        $num += intval($iparr[$i]) * pow(256,count($iparr)-($i+1));

    }

    return $num;

}

 

echo  $ip.'<br />';

$ip_int = ipToInt($ip);

echo $ip_int.'<br />';

echo long2ip($ip_int);

输出:
0210.110.11.49

3530427185

210.110.11.49

第二、通过位运算符

$ip = '0210.110.11.49';

 

function ipToInt($ip){

    $iparr = explode('.',$ip);

    return (intval($iparr[0]<<24))|(intval($iparr[1])<<16)|(intval($iparr[2])<<8)| (intval($iparr[3]));

}

 

echo  $ip.'<br />';

$ip_int = ipToInt($ip);

echo $ip_int.'<br />';

echo long2ip($ip_int);

输出:
0210.110.11.49

-764540111

210.110.11.49

检测IP是否合法

第一、自己遍历检测

function check_ip($ip){

    $iparr = explode('.',$ip);

    foreach($iparr as $v){ if($v>255) return false; }

    return true;

}

 

echo '210.285.11.49,';

var_dump(check_ip('210.285.11.49'));

echo '<br />';

echo '210.205.11.49,';

var_dump(check_ip('210.205.11.49'));

[code]
输出:

[code]

210.285.11.49,bool(false)

210.205.11.49,bool(true)

第二、使用ip2long返回
function check_ip($ip){

    if(ip2long($ip)) return true;

    return false;

}

 

echo '210.285.11.49,';

var_dump(check_ip('210.285.11.49'));

echo '<br />';

echo '210.205.11.49,';

var_dump(check_ip('210.205.11.49'));

输出:
210.285.11.49,bool(false)

210.205.11.49,bool(true)

后记

不少人把ip写库用ip2long转换存放int类型的字段中,但是,在不同的系统平台上,ip2long函数得到的值是不同的,因此可能造成在从数据库中读出数据逆转ip时用long2ip得到的ip与原ip不符合
如果是mysql可以使用mysql系统函数INET_ATON与INET_NTOA解决,或者使用bigint类型处理,要么自己写函数。

PHP 相关文章推荐
php下图片文字混合水印与缩略图实现代码
Dec 11 PHP
smarty获得当前url的方法分享
Feb 14 PHP
ThinkPHP3.1之D方法实例详解
Jun 20 PHP
PHP模拟登陆163邮箱发邮件及获取通讯录列表的方法
Mar 07 PHP
PHP实现删除字符串中任何字符的函数
Aug 11 PHP
Thinkphp实现自动验证和自动完成
Dec 19 PHP
Yii2主题(Theme)用法详解
Jul 23 PHP
php登录超时检测功能实例详解
Mar 21 PHP
php中的异常和错误浅析
May 03 PHP
Yii2第三方类库插件Imagine的安装和使用
Jul 06 PHP
windows下的WAMP环境搭建图文教程(推荐)
Jul 27 PHP
如何通过Apache在本地配置多个虚拟主机
Jul 29 PHP
PHP函数http_build_query使用详解
Aug 20 #PHP
PHP函数in_array()使用详解
Aug 20 #PHP
PHP中使用json数据格式定义字面量对象的方法
Aug 20 #PHP
PHP采用自定义函数实现遍历目录下所有文件的方法
Aug 19 #PHP
浅谈php函数serialize()与unserialize()的使用方法
Aug 19 #PHP
PHP将回调函数作用到给定数组单元的方法
Aug 19 #PHP
php实现文件下载代码分享
Aug 19 #PHP
You might like
php trim 去除空字符的定义与语法介绍
2010/05/31 PHP
php数组函数序列之end() - 移动数组内部指针到最后一个元素,并返回该元素的值
2011/10/31 PHP
php字符串截取的简单方法
2013/07/04 PHP
浅谈php优化需要注意的地方
2014/11/27 PHP
php实现图片转换成ASCII码的方法
2015/04/03 PHP
微信API接口大全
2015/04/15 PHP
PHP常用操作类之通信数据封装类的实现
2017/07/16 PHP
使用vs code编辑调试php配置的方法
2019/01/29 PHP
在laravel框架中实现封装公共方法全局调用
2019/10/14 PHP
jquery 3D球状导航的文章分类
2010/07/06 Javascript
Javascript中的异步编程规范Promises/A详细介绍
2014/06/06 Javascript
jQuery Validate表单验证入门学习
2015/12/18 Javascript
如何使用headjs来管理和异步加载js
2016/11/29 Javascript
ES6概念 Symbol.keyFor()方法
2016/12/25 Javascript
js 监控iframe URL的变化实例代码
2017/07/12 Javascript
纯js代码生成可搜索选择下拉列表的实例
2018/01/11 Javascript
AnglarJs中的上拉加载实现代码
2018/02/08 Javascript
vue操作动画的记录animate.css实例代码
2019/04/26 Javascript
vue中node_modules中第三方模块的修改使用详解
2019/05/31 Javascript
Vue.js实现立体计算器
2020/02/22 Javascript
nodejs各种姿势断点调试的方法
2020/06/18 NodeJs
在antd中setFieldsValue和defaultVal的用法
2020/10/29 Javascript
Pycharm技巧之代码跳转该如何回退
2017/07/16 Python
Python基于OpenCV实现视频的人脸检测
2018/01/23 Python
pandas数据筛选和csv操作的实现方法
2019/07/02 Python
PyTorch笔记之scatter()函数的使用
2020/02/12 Python
基于python实现百度语音识别和图灵对话
2020/11/02 Python
高中生校园生活自我评价
2013/09/19 职场文书
2014年开学第一课活动方案
2014/03/06 职场文书
金融保险专业求职信
2014/09/03 职场文书
就业证明函
2015/06/17 职场文书
教师教育心得体会
2016/01/19 职场文书
pandas 实现将NaN转换为None
2021/05/14 Python
python实现局部图像放大
2021/11/17 Python
PostgreSQL自动更新时间戳实例代码
2021/11/27 PostgreSQL
MySQL事务的ACID特性以及并发问题方案
2022/07/15 MySQL