php查询ip所在地的方法


Posted in PHP onDecember 05, 2014

本文实例讲述了php查询ip所在地的方法。分享给大家供大家参考。

具体实现方法如下:

<?php 

/** 

*@ date         2010.12.21 

注:文件头 [第一条索引的偏移量 (4byte)] + [最后一条索引的偏移地址 (4byte)]     8字节 

记录区 [结束ip (4byte)] + [地区1] + [地区2]                                4字节+不定长 

索引区 [开始ip (4byte)] + [指向记录区的偏移地址 (3byte)]                   7字节 

*/ 

class iplocation{ 

var $fp; 

var $firstip;  //第一条ip索引的偏移地址 

var $lastip;   //最后一条ip索引的偏移地址 

var $totalip;  //总ip数 

/* 

|---------------------------------------------------------------------------- 

| 构造函数,初始化一些变量 

|---------------------------------------------------------------------------- 

| 

*/ 

function iplocation($datfile = "qqwry.dat"){ 

$this->fp=fopen($datfile,'rb')or die("qqwry.dat不存在,请去网上 <a href='https://3water.com/softs/10529.html'>下载纯真ip数据 库</a>, 'qqwry.dat' 放到当前目录下");   //二制方式打开 

$this->firstip = $this->get4b(); //第一条ip索引的绝对偏移地址 

$this->lastip = $this->get4b();  //最后一条ip索引的绝对偏移地址 

$this->totalip =($this->lastip - $this->firstip)/7 ; //ip总数 索引区是定长的7个字节,在此要除以7, 

register_shutdown_function(array($this,"closefp"));  //为了兼容php5以下版本,本类没有用析构函数,自动关闭ip库. 

} 

/* 

|---------------------------------------------------------------------------- 

| 关闭ip库 

|---------------------------------------------------------------------------- 

| 

*/ 

function closefp(){ 

fclose($this->fp); 

} 

/* 

|---------------------------------------------------------------------------- 

| 读取4个字节并将解压成long的长模式 

|---------------------------------------------------------------------------- 

| 

*/ 

function get4b(){ 

$str=unpack("v",fread($this->fp,4)); 

return $str[1]; 

} 

/* 

|---------------------------------------------------------------------------- 

| 读取重定向了的偏移地址 

|---------------------------------------------------------------------------- 

| 

*/ 

function getoffset(){ 

$str=unpack("v",fread($this->fp,3).chr(0)); 

return $str[1]; 

} 

/* 

|---------------------------------------------------------------------------- 

| 读取ip的详细地址信息 

|---------------------------------------------------------------------------- 

| 

*/ 

function getstr(){ 

$split=fread($this->fp,1); 

while (ord($split)!=0) { 

$str .=$split; 

$split=fread($this->fp,1); 

} 

return $str; 

} 

/* 

|---------------------------------------------------------------------------- 

| 将ip通过ip2long转成ipv4的互联网地址,再将他压缩成big-endian字节序 ,用来和索引区内的ip地址做比较 

|---------------------------------------------------------------------------- 

| 

*/ 

function iptoint($ip){ 

return pack("n",intval(ip2long($ip))); 

} 

/* 

|---------------------------------------------------------------------------- 

| 获取地址信息 

|---------------------------------------------------------------------------- 

| 

*/ 

function readaddress(){ 

$now_offset=ftell($this->fp); //得到当前的指针位址 

$flag=$this->getflag(); 

switch (ord($flag)){ 

case 0: 

$address=""; 

break; 

case 1: 

case 2: 

fseek($this->fp,$this->getoffset()); 

$address=$this->getstr(); 

break; 

default: 

fseek($this->fp,$now_offset); 

$address=$this->getstr(); 

break; 

} 

return $address; 

} 

/* 

|---------------------------------------------------------------------------- 

| 获取标志1或2   用来确定地址是否重定向了 

|---------------------------------------------------------------------------- 

| 

*/ 

function getflag(){ 

return fread($this->fp,1); 

} 

/* 

|---------------------------------------------------------------------------- 

| 用二分查找法在索引区内搜索ip 

|---------------------------------------------------------------------------- 

| 

*/ 

function searchip($ip){ 

$ip=gethostbyname($ip);     //将域名转成ip 

$ip_offset["ip"]=$ip; 

$ip=$this->iptoint($ip);    //将ip转换成长整型 

$firstip=0;                 //搜索的上边界 

$lastip=$this->totalip;     //搜索的下边界 

$ipoffset=$this->lastip;    //初始化为最后一条ip地址的偏移地址 

while ($firstip <= $lastip){ 

$i=floor(($firstip + $lastip) / 2);          //计算近似中间记录 floor函数记算给定浮点数小的最大整数,说白了就是四舍五也舍 

fseek($this->fp,$this->firstip + $i * 7);    //定位指针到中间记录 

$startip=strrev(fread($this->fp,4));         //读取当前索引区内的开始ip地址,并将其little-endian的字节序转换成big-endian的字节序 

if ($ip < $startip) { 

$lastip=$i - 1; 

} 

else { 

fseek($this->fp,$this->getoffset()); 

$endip=strrev(fread($this->fp,4)); 

if ($ip > $endip){ 

$firstip=$i + 1; 

} 

else { 

$ip_offset["offset"]=$this->firstip + $i * 7; 

break; 

} 

} 

} 

return $ip_offset; 

} 

/* 

|---------------------------------------------------------------------------- 

| 获取ip地址详细信息 

|---------------------------------------------------------------------------- 

| 

*/ 

function getaddress($ip){ 

$ip_offset=$this->searchip($ip);  //获取ip 在索引区内的绝对编移地址 

$ipoffset=$ip_offset["offset"]; 

$address["ip"]=$ip_offset["ip"]; 

fseek($this->fp,$ipoffset);      //定位到索引区 

$address["startip"]=long2ip($this->get4b()); //索引区内的开始ip 地址 

$address_offset=$this->getoffset();            //获取索引区内ip在ip记录区内的偏移地址 

fseek($this->fp,$address_offset);            //定位到记录区内 

$address["endip"]=long2ip($this->get4b());   //记录区内的结束ip 地址 

$flag=$this->getflag();                      //读取标志字节 

switch (ord($flag)) { 

case 1:  //地区1地区2都重定向 

$address_offset=$this->getoffset();   //读取重定向地址 

fseek($this->fp,$address_offset);     //定位指针到重定向的地址 

$flag=$this->getflag();               //读取标志字节 

switch (ord($flag)) { 

case 2:  //地区1又一次重定向, 

fseek($this->fp,$this->getoffset()); 

$address["area1"]=$this->getstr(); 

fseek($this->fp,$address_offset+4);      //跳4个字节 

$address["area2"]=$this->readaddress();  //地区2有可能重定向,有可能没有 

break; 

default: //地区1,地区2都没有重定向 

fseek($this->fp,$address_offset);        //定位指针到重定向的地址 

$address["area1"]=$this->getstr(); 

$address["area2"]=$this->readaddress(); 

break; 

} 

break; 

case 2: //地区1重定向 地区2没有重定向 

$address1_offset=$this->getoffset();   //读取重定向地址 

fseek($this->fp,$address1_offset);   

$address["area1"]=$this->getstr(); 

fseek($this->fp,$address_offset+8); 

$address["area2"]=$this->readaddress(); 

break; 

default: //地区1地区2都没有重定向 

fseek($this->fp,$address_offset+4); 

$address["area1"]=$this->getstr(); 

$address["area2"]=$this->readaddress(); 

break; 

} 

//*过滤一些无用数据 

if (strpos($address["area1"],"cz88.net")!=false){ 

$address["area1"]="未知"; 

} 

if (strpos($address["area2"],"cz88.net")!=false){ 

$address["area2"]=" "; 

} 

return $address; 

} 

} 

 

/*用法如下:*/ 

$ip=new iplocation("qqwry.dat"); 

$address=$ip->getaddress("61.129.51.27"); 

//$address=$ip->getaddress(3water.com); 

echo '<pre>'; 

print_r($address); 

?>

希望本文所述对大家的PHP程序设计有所帮助。

PHP 相关文章推荐
一个比较简单的PHP 分页分组类
Dec 10 PHP
使用JSON实现数据的跨域传输的php代码
Dec 20 PHP
深入探讨:PHP使用数据库永久连接方式操作MySQL的是与非
Jun 05 PHP
php备份数据库类分享
Apr 14 PHP
php使用gzip压缩传输js和css文件的方法
Jul 29 PHP
简单介绍win7下搭建apache+php+mysql开发环境
Aug 06 PHP
php提交过来的数据生成为txt文件
Apr 28 PHP
CI框架支持$_GET的两种实现方法
May 18 PHP
老生常谈PHP面向对象之注册表模式
May 26 PHP
通过PHP设置BugFree获取邮箱通知
Apr 25 PHP
使用laravel和ajax实现整个页面无刷新的操作方法
Oct 03 PHP
PHP使用redis位图bitMap 实现签到功能
Oct 08 PHP
smarty实现多级分类的方法
Dec 05 #PHP
Codeigniter框架实现获取分页数据和总条数的方法
Dec 05 #PHP
常见php数据文件缓存类汇总
Dec 05 #PHP
Thinkphp搜索时首页分页和搜索页保持条件分页的方法
Dec 05 #PHP
ThinkPHP模版引擎之变量输出详解
Dec 05 #PHP
ThinkPHP添加更新标签的方法
Dec 05 #PHP
彻底删除thinkphp3.1案例blog标签的方法
Dec 05 #PHP
You might like
Windows 下的 PHP-PEAR 安装方法
2010/11/20 PHP
延长phpmyadmin登录时间的方法
2011/02/06 PHP
php自动给文章加关键词链接的函数代码
2012/11/29 PHP
ThinkPHP CURD方法之where方法详解
2014/06/18 PHP
Yii2选项卡的简单使用
2017/05/26 PHP
PHP中Session ID的实现原理实例分析
2019/08/17 PHP
在Laravel中使用GuzzleHttp调用第三方服务的API接口代码
2019/10/15 PHP
jquery jqPlot API 中文使用教程(非常强大的图表工具)
2011/08/15 Javascript
jQuery源码分析-01总体架构分析
2011/11/14 Javascript
idTabs基于JQuery的根据URL参数选择Tab插件
2012/04/11 Javascript
圣诞节Merry Christmas给博客添加浪漫的下雪效果基于jquery实现
2012/12/27 Javascript
js 中将多个逗号替换为一个逗号的代码
2014/06/07 Javascript
JS遍历Json字符串中键值对先转成JSON对象再遍历
2014/08/15 Javascript
JavaScript Math.round() 方法
2015/12/18 Javascript
jquery中validate与form插件提交的方式小结
2016/03/26 Javascript
浅谈js中test()函数在正则中的使用
2016/08/19 Javascript
微信小程序开发之IOS和Android兼容的问题
2017/09/26 Javascript
关于Vue背景图打包之后访问路径错误问题的解决
2017/11/03 Javascript
Jquery获取radio选中值实例总结
2019/01/17 jQuery
谈谈JavaScript令人迷惑的==与+
2020/08/31 Javascript
python中for语句简单遍历数据的方法
2015/05/07 Python
scrapy spider的几种爬取方式实例代码
2018/01/25 Python
java中两个byte数组实现合并的示例
2018/05/09 Python
python 识别图片中的文字信息方法
2018/05/10 Python
Python爬虫实现验证码登录代码实例
2019/05/10 Python
python 梯度法求解函数极值的实例
2019/07/10 Python
Django组件content-type使用方法详解
2019/07/19 Python
在win64上使用bypy进行百度网盘文件上传功能
2020/01/02 Python
Iconfont(矢量图标)+iconmoon(图标svg互转)配合javascript实现社交分享系统
2020/04/21 Python
Harrods美国:英国最大的百货公司
2018/11/04 全球购物
毕业生的求职信范文分享
2013/12/04 职场文书
网络书店创业计划书
2014/02/07 职场文书
出国留学计划书
2014/04/27 职场文书
六年级学生期末评语
2014/12/26 职场文书
矛盾论读书笔记
2015/06/29 职场文书
毕业生入职感言
2015/07/31 职场文书