PHP获取IP地址所在地信息的实例(使用纯真IP数据库qqwry.dat)


Posted in PHP onNovember 15, 2016

如下所示:

<?php
 $data = '254.254.254.254';
 echo ip2long($data);
 
 
 function getIP()
 {
   if(getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
   $ip = getenv("HTTP_CLIENT_IP");
   elseif(getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
   $ip = getenv("HTTP_X_FORWARDED_FOR");
   elseif (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
   $ip = getenv("REMOTE_ADDR");
   elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
   $ip = $_SERVER['REMOTE_ADDR'];
   else
   $ip = "0.0.0.0";
   return $ip;
 }
 
 
 class IpLocation {
   //数据文件指针
   var $fp;
   var $firstip;
   var $lastip;
   var $totalip;
 
 
   function getlong() {
    //unpack从二进制字符串对数据进行解包
    //将读取的little-endian编码的4个字节转化为长整型数,fread安全读取二进制文件
    $result = unpack('Vlong', fread($this->fp, 4));
    return $result['long'];
   }
 
 
   function getlong3() {
    //将读取的little-endian编码的3个字节转化为长整型数
    $result = unpack('Vlong', fread($this->fp, 3).chr(0));
    return $result['long'];
   }
 
 
   function packip($ip) {
    //pack把数据装入一个二进制字符串
    //ip2long将IP地址转成无符号的长整型,也可以用来验证IP地址
    return pack('N', intval(ip2long($ip)));
   }
 
 
   function getstring($data = "") {
    $char = fread($this->fp, 1);
    while (ord($char) > 0) {    //ord返回字符的ASCII值,字符串按照C格式保存,以\0结束
      $data .= $char;
      $char = fread($this->fp, 1);
    }
    return $data;
   }
 
 
   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;
   }
 
 
   function getlocation($ip) {
    if (!$this->fp) return null;      // 如果数据文件没有被正确打开,则直接返回空
    $location['ip'] = gethostbyname($ip);  // 域名转化为IP地址
    $ip = $this->packip($location['ip']);  // 将输入的IP地址转化为可比较的IP地址
    // 不合法的IP地址会被转化为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反转字符串
      // strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式,便于比较
      //关于little-endian与big-endian 参考:http://baike.baidu.com/view/2368412.htm
      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;       // 则表示找到结果,退出循环
        }
      }
    }
 
 
    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'] == " CZNET") { // CZNET表示没有有效信息
      $location['country'] = "未知";
    }
    if ($location['area'] == " CZNET") {
      $location['area'] = "";
    }
    return $location;
   }
   /**
   * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息
   */
   function IpLocation($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;
      //注册析构函数,使其在程序执行结束时执行
      register_shutdown_function(array(&$this, '_IpLocation'));
    }
   }
   /**
   * 析构函数,用于在页面执行结束后自动关闭打开的文件
   */
   function _IpLocation() {
    if ($this->fp) {
      fclose($this->fp);
    }
    $this->fp = 0;
   }
 }
 header("content-Type: text/html; charset=gbk");
 $ipOrDomain='110.0.0.0';
 //$ipOrDomain='www.baidu.com';
 $iplocation = new IpLocation();
 $location = $iplocation->getlocation($ipOrDomain);
 $address=mb_convert_encoding($location['country'].$location['area'], "gbk", "gbk");
 echo $address;
 ?>

以上这篇PHP获取IP地址所在地信息的实例(使用纯真IP数据库qqwry.dat)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP聊天室技术
Oct 09 PHP
PHP3 safe_mode 失效漏洞
Oct 09 PHP
超级好用的一个php上传图片类(随机名,缩略图,加水印)
Jun 30 PHP
php中选择什么接口(mysql、mysqli)访问mysql
Feb 06 PHP
浅析PHP安装扩展mcrypt以及相关依赖项(PHP安装PECL扩展的方法)
Jul 05 PHP
php使用curl发送json格式数据实例
Dec 17 PHP
php中memcache 基本操作实例
May 17 PHP
PHP中FTP相关函数小结
Jul 15 PHP
在Thinkphp中使用ajax实现无刷新分页的方法
Oct 25 PHP
PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)
Sep 17 PHP
php+redis实现商城秒杀功能
Nov 19 PHP
PHP哈希表实现算法原理解析
Dec 11 PHP
php读取qqwry.dat ip地址定位文件的类实例代码
Nov 15 #PHP
thinkPHP内置字符串截取函数用法详解
Nov 15 #PHP
ThinkPHP简单使用memcache缓存的方法
Nov 15 #PHP
php compact 通过变量创建数组
Nov 15 #PHP
PHP多维数组元素操作类的方法
Nov 14 #PHP
浅谈PHP中关于foreach使用引用变量的坑
Nov 14 #PHP
利用switch语句进行多选一判断的实例代码
Nov 14 #PHP
You might like
php构造方法中析构方法在继承中的表现
2016/04/12 PHP
24条货真价实的PHP代码优化技巧
2016/07/28 PHP
PHP preg_match实现正则表达式匹配功能【输出是否匹配及匹配值】
2017/07/19 PHP
PHP新特性之字节码缓存和内置服务器
2017/08/11 PHP
JQuery获取浏览器窗口内容部分高度的代码
2012/02/24 Javascript
实用的JS正则表达式(手机号码/IP正则/邮编正则/电话等)
2013/01/11 Javascript
JS+CSS实现美化的下拉列表框效果
2015/08/11 Javascript
JavaScript知识点整理
2015/12/09 Javascript
Node.js实现文件上传
2016/07/05 Javascript
React 子组件向父组件传值的方法
2017/07/24 Javascript
View.post() 不靠谱的地方你知道多少
2017/08/29 Javascript
微信小程序用户授权,以及判断登录是否过期的方法
2019/05/10 Javascript
JS中的算法与数据结构之字典(Dictionary)实例详解
2019/08/20 Javascript
layui复选框限制选择个数的方法
2019/09/18 Javascript
初步理解Python进程的信号通讯
2015/04/09 Python
在Lighttpd服务器中运行Django应用的方法
2015/07/22 Python
Windows下安装python MySQLdb遇到的问题及解决方法
2017/03/16 Python
用pickle存储Python的原生对象方法
2017/04/28 Python
用Python设计一个经典小游戏
2017/05/15 Python
Python爬虫实现百度图片自动下载
2018/02/04 Python
PyCharm设置护眼背景色的方法
2018/10/29 Python
python实现蒙特卡罗方法教程
2019/01/28 Python
Python统计一个字符串中每个字符出现了多少次的方法【字符串转换为列表再统计】
2019/05/05 Python
Python缓存技术实现过程详解
2019/09/25 Python
Python多线程爬取豆瓣影评API接口
2019/10/22 Python
Python线程协作threading.Condition实现过程解析
2020/03/12 Python
python如何导入依赖包
2020/07/13 Python
python math模块的基本使用教程
2021/01/16 Python
python基于pexpect库自动获取日志信息
2021/02/01 Python
Python制作运行进度条的实现效果(代码运行不无聊)
2021/02/24 Python
英文简历中的自荐信范文
2013/12/14 职场文书
公司授权委托书样本
2014/09/15 职场文书
人事文员岗位职责
2015/02/04 职场文书
2019旅游导游工作总结
2019/06/27 职场文书
i5-10400f处理相当于i7多少水平
2022/04/19 数码科技
Vue router配置与使用分析讲解
2022/12/24 Vue.js