php查询ip所在地代码,php查询ip所在地的方法

by admin on 2019年7月18日

本文实例陈述了php查询ip所在地的主意。分享给大家供大家参照他事他说加以考察。

<?php教程
/**
*@ date         2010.12.21
*@ author       王刚
*@ email        373882774@qq.com
*@ qq           373882774
注:文件头 [首先条索引的偏移量 (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=’
库</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[bf88必发唯一官网,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();
php查询ip所在地代码,php查询ip所在地的方法。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(“221.231.102.100”);
//$address=$ip->getaddress(www.111cn.net);
echo ‘<pre>’;
print_r($address);
?>

ip地址询问,ip查询,ip所在地查询

dat文件,关于ip对应地区的音讯文件
qqwry.dat文件
网络和煦下载

切切实实贯彻格局如下:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“”>
<html xmlns=””>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″
/>
<title>ip归属地</title>

class类文件,解析qqwry.data文件的
IpLocation.php文件

复制代码 代码如下:

</head>
<body>
<h1>站长爱好者网IP地址询问</h1>
<form id=”form1″ name=”form1″ method=”post” action=””>
  <input type=”text” name=”ipinfo” id=”ipinfo” style=”border:solid
1px #fdbdd5″ />
  <input type=”submit” name=”button” id=”button” value=”查询”
style=”border:solid 1px #fdbdd5;width:50px” />
</form>
<?php
include(“ipcheck.class.php”);
$ipinfo=$_POST[‘ipinfo’];
$iptest=new IpLocation();
echo $iptest->getlocation($ipinfo);
?>
</body>
</html>
好以往来拜谒ipcheck.class.php文件.

复制代码 代码如下:

<?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=’//www.jb51.net/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库.
}
/*
|—————————————————————————-
php查询ip所在地代码,php查询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(www.jb51.net);
echo ‘<pre>’;
print_r($address);
?>

<?php
/**
* @author 网事如风
* E-mail:rainrenamy@gmail.com
* 个人网站:
* 演示地址:http;//www.adminfan.com/seo/ip.php
*/
class IpLocation {
/**
* QQWry.Dat文件指针
* @var resource
*/
var $fp;
/**
* 第一条IP记录的撼动地址
*
* @var int
*/
var $firstip;
/**
* 最终一条IP记录的舞狮地址
*
* @var int
*/

<?php
class IpLocation {
    /**
    * @var resource 指针
    */
    private $fp;
    /**
    * 第一条IP记录的舞狮地址
    * @var int
    */
    private $firstip;
    /**
    * 最终一条IP记录的偏移地址
    * @var int
    */
    private $lastip;
    /**
    * IP记录的总条数(不含有版本信息记录)
    * @var int
    */
    private $totalip;
    /**
    * 构造函数,展开 QQWry.Dat 文件并起先化类中的新闻
    * @param string $filename
    * @return IpLocation
    */
    public function __construct($filename = “qqwry.dat”) {
        $this->fp = 0;
        if (($this->fp = @fopen($filename, ‘rb’)) !== false) {
            $this->firstip = $this->getlong();
            $this->lastip = $this->getlong();
            $this->totalip = ($this->lastip – $this->firstip) /
7;
        }
    }
    /**
    * 重临读取的长整型数
    * @access private
    * @return int
    */
    public function getlong() {
        //将读取的little-endian编码的4个字节转化为长整型数
        $result = unpack(‘Vlong’, fread($this->fp, 4));
        return $result[‘long’];
    }
    /**
    * 重临读取的3个字节的长整型数
    *
    * @access private
    * @return int
    */
    public function getlong3() {
        //将读取的little-endian编码的3个字节转化为长整型数
        $result = unpack(‘Vlong’, fread($this->fp, 3).chr(0));
        return $result[‘long’];
    }
    /**
    * 重返压缩后可开始展览相比的IP地址
    *
    * @access private
    * @param string $ip
    * @return string
    */
    public function packip($ip) {
        //
将IP地址转化为长整型数,若是在PHP5中,IP地址错误,则赶回False,
        //
那时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串
        return pack(‘N’, intval(ip2long($ip)));
    }
    /**
    * 再次来到读取的字符串
    *
    * @access private
    * @param string $data
    * @return string
    */
    public function getstring($data = “”) {
        $char = fread($this->fp, 1);
        while (ord($char) > 0) { // 字符串遵照C格式保存,以\0结束
            $data .= $char; // 将读取的字符连接到给定字符串之后
            $char = fread($this->fp, 1);
        }
        return mb_convert_encoding($data, ‘utf-8’, ‘gb2312’);
    }
    /**
    * 重临地区音讯
    *
    * @access private
    * @return string
    */
    public function getarea() {
        $byte = fread($this->fp, 1); // 标记字节
        switch (ord($byte)) {
            case 0: // 未有区域信息
                $area = “”;
            break;
            case 1:
            case 2: // 标记字节为1或2,表示区域音讯被重定向
                fseek($this->fp, $this->getlong3());
                $area = $this->getstring();
            break;
            default: // 不然,表示区域新闻尚未被重定向
                $area = $this->getstring($byte);
            break;
        }
        return $area;
    }
    /**
    * 依照所给 IP 地址或域名再次回到内地地区信息
    * @access public
    * @param string $ip
    * @return array
    */
    function getlocation($ip) {
        if (!$this->fp) return null; //
若是数据文件未有被科学张开,则一直回到空
        $location[‘ip’] = gethostbyname($ip); //
将输入的域名转化为IP地址
        $ip = $this->packip($location[‘ip’]); //
将输入的IP地址转化为可正如的IP地址
        // 不合规的IP地址会被转接为255.255.255.255
        // 对分查找
        $l = 0; // 寻觅的下面界
        $u = $this->totalip; // 找寻的上面界
        $findip = $this->lastip; //
若无找到就赶回最终一条IP记录(QQWry.Dat的版本音讯)
        while ($l <= $u) { // 当上面界小于上面际时,查找未果
            $i = floor(($l + $u) / 2); // 总计近似中间记录
            fseek($this->fp, $this->firstip + $i * 7);
            $beginip = strrev(fread($this->fp, 4)); //
获取中间记录的发轫IP地址
            //
strrev函数在此处的魔法是将little-endian的压缩IP地址转化为big-endian的格式
            // 以便用于相比较,前边同样。
            if ($ip < $beginip) { //
用户的IP小于中间记录的发端IP地址时
                $u = $i – 1; // 将追寻的上面界修改为中等记录减一
            }else{
                fseek($this->fp, $this->getlong3());
                $endip = strrev(fread($this->fp, 4)); //
获取中间记录的终止IP地址
                if ($ip > $endip) { //
用户的IP大于中间记录的扫尾IP地址时
                    $l = $i + 1; // 将追寻的上边界修改为中等记录加一
                }else{ // 用户的IP在个中记录的IP范围内时
                    $findip = $this->firstip + $i * 7;
                    break; // 则代表找到结果,退出循环
                }
            }
        }
        //获取查找到的IP地理地点音信
        fseek($this->fp, $findip);
        $location[‘beginip’] = long2ip($this->getlong()); //
用户IP所在范围的起先地址
        $offset = $this->getlong3();
        fseek($this->fp, $offset);
        $location[‘endip’] = long2ip($this->getlong()); //
用户IP所在范围的停止地址
        $byte = fread($this->fp, 1); // 标记字节
        switch (ord($byte)) {
            case 1: // 标记字节为1,表示国家和区域音讯都被同一时间重定向
                $countryOffset = $this->getlong3(); // 重定向地址
                fseek($this->fp, $countryOffset);
                $byte = fread($this->fp, 1); // 标识字节
                switch (ord($byte)) {
                    case 2: // 标识字节为2,表示国家音信又被重定向
                        fseek($this->fp, $this->getlong3());
                        $location[‘country’] =
$this->getstring();
                        fseek($this->fp, $countryOffset + 4);
                        $location[‘area’] = $this->getarea();
                        break;
                    default: // 不然,表示国家新闻未有被重定向
                        $location[‘country’] =
$this->getstring($byte);
                        $location[‘area’] = $this->getarea();
                        break;
                }
                break;
            case 2: // 标识字节为2,表示国家消息被重定向
                fseek($this->fp, $this->getlong3());
                $location[‘country’] = $this->getstring();
                fseek($this->fp, $offset + 8);
                $location[‘area’] = $this->getarea();
                break;
            default: // 不然,表示国家音信尚未被重定向
                $location[‘country’] = $this->getstring($byte);
                $location[‘area’] = $this->getarea();
                break;
        }
        if ($location[‘country’] == ” CZ88.NET”) { //
CZ88.NET表示从未立见成效新闻
            $location[‘country’] = “未知”;
        }
        if ($location[‘area’] == ” CZ88.NET”) {
            $location[‘area’] = “”;
        }
        return $location;
    }

愿意本文所述对大家的PHP程序设计有着协助。

var $lastip;

    /**
    * 析构函数,用于在页面实行完结后自行关闭张开的文本。
    *
    */
    function __desctruct() {
        if ($this->fp) {
            fclose($this->fp);
        }
        $this->fp = 0;
    }
}
?>

你只怕感兴趣的稿子:

  • PHP中依照IP地址剖断城市落成城市切换或跳转代码
  • 浅析php依据ip查询所在地方(极度有用,中华英才网就用到)
  • PHP依照IP地址获取所在城市具体达成
  • PHP决断IP并转跳到相应城市分站的办法
  • php完结基于IP地址获取其所在省市的法门

/**
* IP记录的总条数(不含有版本消息记录)
*
* @var int
*/

其一也足以英特网下载,也能够copy这里的,这里的也是很全的。
实行文书,笔者那边叫ip_location.php文件

var $totalip;

复制代码 代码如下:

/**
* 再次回到读取的长整型数
*
* @access private
* @return int
*/

<?php
function getIpPlace(){
 require_once(“IpLocation.php”)//加载类文件IpLocation.php
 $ipfile = “qqwry.dat”;  //获取ip对应地区的音信文件
 $iplocation = new IpLocation($ipfile); //new IpLocation($ipfile)
$ipfile ip对应地区音讯文件
 $ipresult = $iplocation->getlocation(“ip地址”); //依照ip地址获得地方getlocation(“ip地区”)
 return $ipresult;
}
print_r($getIpPlace()); //调用艺术
?>

function getlong() {

您也许感兴趣的篇章:

  • PHP中依据IP地址判定城市完结城市切换或跳转代码
  • PHP根据IP地址获取所在城市具体贯彻
  • php查询ip所在地的方法
  • PHP剖断IP并转跳到相应城市分站的点子
  • php实现基于IP地址获取其所在省市的章程

//将读取的little-endian编码的4个字节转化为长整型数

$result = unpack(‘Vlong’, fread($this->fp, 4));

return $result[‘long’];

}

/**
* 重临读取的3个字节的长整型数
*
* @access private
* @return int
*/

function getlong3() {

//将读取的little-endian编码的3个字节转化为长整型数

$result = unpack(‘Vlong’, fread($this->fp, 3).chr(0));

return $result[‘long’];

}

/**
* 重临压缩后可开始展览相比较的IP地址
*
* @access private
* @param string $ip
* @return string
*/

function packip($ip) {

// 将IP地址转化为长整型数,假设在PHP5中,IP地址错误,则赶回False,

// 那时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串

return pack(‘N’, intval(ip2long($ip)));

}

/**
* 重返读取的字符串
*
* @access private
* @param string $data
* @return string
*/

function getstring($data = “”) {

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

while (ord($char) > 0) { // 字符串根据C格式保存,以\0结束

$data .= $char; // 将读取的字符连接到给定字符串之后

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

}

return $data;

}

/**
* 再次来到地区音讯
*
* @access private
* @return string
*/

function getarea() {

$byte = fread($this->fp, 1); // 标记字节

switch (ord($byte)) {

case 0: // 没有区域音讯

$area = “”;

break;

case 1:

case 2: // 标记字节为1或2,表示区域音信被重定向

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

$area = $this->getstring();

break;

default: // 否则,表示区域音信未有被重定向

$area = $this->getstring($byte);

break;

}

return $area;

}

/**
* 遵照所给 IP 地址或域名重返外省地点音信
*
* @access public
* @param string $ip
* @return array
*/

function getlocation($ip) {

if (!$this->fp) return null; //
如若数据文件未有被科学展开,则一贯回到空

$location[‘ip’] = gethostbyname($ip); // 将输入的域名转化为IP地址
$ip = $this->packip($location[‘ip’]); //
将输入的IP地址转化为可正如的IP地址
// 不合规的IP地址会被转化为255.255.255.255
// 对分查找
$l = 0; // 寻觅的上面界
$u = $this->totalip; // 寻找的下面界
$findip = $this->lastip; //
若无找到就回去最终一条IP记录(QQWry.Dat的版本信息)
while ($l <= $u) { // 当上面界小于下面际时,查找未果

$i = floor(($l + $u) / 2); // 总计近似中间记录

fseek($this->fp, $this->firstip + $i * 7);

$beginip = strrev(fread($this->fp, 4)); // 获取中间记录的始发IP地址

//
strrev函数在此地的作用是将little-endian的压缩IP地址转化为big-endian的格式

// 以便用于比较,后边一样。

if ($ip < $beginip) { // 用户的IP小于中间记录的始发IP地址时

$u = $i – 1; // 将搜索的上面界修改为中等记录减一

}

else {

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

$endip = strrev(fread($this->fp, 4)); // 获取中间记录的利落IP地址

if ($ip > $endip) { // 用户的IP大于中间记录的终止IP地址时

$l = $i + 1; // 将搜索的上面界修改为中等记录加一

}

else { // 用户的IP在中等记录的IP范围内时

$findip = $this->firstip + $i * 7;
break; // 则意味找到结果,退出循环

}

}

}

//获取查找到的IP地理地方音信
fseek($this->fp, $findip);
$location[‘beginip’] = long2ip($this->getlong()); //
用户IP所在范围的启幕地址
$offset = $this->getlong3();
fseek($this->fp, $offset);
$location[‘endip’] = long2ip($this->getlong()); //
用户IP所在范围的结束地址
$byte = fread($this->fp, 1); // 标识字节
switch (ord($byte)) {

case 1: // 标记字节为1,表示国家和区域音讯都被同有时候重定向

$countryOffset = $this->getlong3(); // 重定向地址

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

$byte = fread($this->fp, 1); // 标识字节

switch (ord($byte)) {

case 2: // 标记字节为2,表示国家新闻又被重定向

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

$location[‘country’] = $this->getstring();

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

$location[‘area’] = $this->getarea();

break;

default: // 不然,表示国家消息并未有被重定向

$location[‘country’] = $this->getstring($byte);

$location[‘area’] = $this->getarea();

break;
}

break;

case 2: // 标识字节为2,表示国家音讯被重定向

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

$location[‘country’] = $this->getstring();

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

$location[‘area’] = $this->getarea();

break;

default: // 不然,表示国家音讯未有被重定向

$location[‘country’] = $this->getstring($byte);

$location[‘area’] = $this->getarea();

break;

}

if ($location[‘country’] == ” CZ88.NET”) { // CZ88.NET表示并未有管用消息

$location[‘country’] = “未知”;

}

if ($location[‘area’] == ” CZ88.NET”) {

$location[‘area’] = “”;

}

//return $location;
echo “你的IP:”.$location[‘ip’].”<br
/>来自”.$location[‘country’].$location[‘area’];

}

/**
* 构造函数,张开 QQWry.Dat 文件并初步化类中的音讯
*
* @param string $filename
* @return IpLocation
*/

function IpLocation($filename = “QQWry.Dat”) {

if (($this->fp = @fopen($filename, ‘rb’)) !== false) {

$this->firstip = $this->getlong();

$this->lastip = $this->getlong();

$this->totalip = ($this->lastip – $this->firstip) / 7;

//注册析构函数,使其在程序实施结束时进行

register_shutdown_function(array(&$this, ‘_IpLocation’));

}

}

/**
* 析构函数,用于在页面实行达成后自动关闭展开的文书。
*
*/

function _IpLocation() {

fclose($this->fp);

}

}

?>

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图