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 htmlentities和htmlspecialchars 的区别
Aug 18 PHP
使用PHP获取网络文件的实现代码
Jan 01 PHP
用sql命令修改数据表中的一个字段为非空(not null)的语句
Jun 04 PHP
PHP session会话的安全性分析
Sep 08 PHP
php代码书写习惯优化小结
Jun 20 PHP
PHP防止跨域提交表单
Nov 01 PHP
实用的PHP带公钥加密类分享(每次加密结果都不一样哦)
Aug 20 PHP
php防止站外远程提交表单的方法
Oct 20 PHP
对于Laravel 5.5核心架构的深入理解
Feb 22 PHP
php中curl和soap方式请求服务超时问题的解决
Jun 11 PHP
PHP实现的微信APP支付功能示例【基于TP5框架】
Sep 16 PHP
Laravel的Auth验证Token验证使用自定义Redis的例子
Sep 30 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一些常用的正则表达式字符的一些转换
2008/07/29 PHP
thinkphp制作404跳转页的简单实现方法
2016/09/22 PHP
thinkphp分页集成实例
2017/07/24 PHP
js日期、星座的级联显示代码
2014/01/23 Javascript
JavaScript中的数组特性介绍
2014/12/30 Javascript
IE及IE6浏览器中判断JS文件加载成功失败的方法
2015/02/18 Javascript
js如何改变文章的字体大小
2016/01/08 Javascript
深入理解$.each和$(selector).each
2016/05/15 Javascript
Highcharts学习之数据列
2016/08/03 Javascript
jQuery与js实现颜色渐变的方法
2016/12/30 Javascript
AngularJS ng-repeat指令中使用track by子语句解决重复数据遍历错误问题
2017/01/21 Javascript
js中DOM三级列表(代码分享)
2017/03/20 Javascript
基于JavaScript实现报警器提示音效果
2017/10/27 Javascript
ES6中数组array新增方法实例总结
2017/11/07 Javascript
解决layui中的form表单与button的点击事件冲突问题
2018/08/15 Javascript
JS中验证整数和小数的正则表达式
2018/10/08 Javascript
[03:01]完美盛典趣味短片 DOTA2年度最佳&拉胯英雄
2019/12/07 DOTA
python使用opencv按一定间隔截取视频帧
2018/03/06 Python
Python 获取div标签中的文字实例
2018/12/20 Python
Python安装selenium包详细过程
2019/07/23 Python
解决Python logging模块无法正常输出日志的问题
2020/02/21 Python
python 爬取B站原视频的实例代码
2020/09/09 Python
python collections模块的使用
2020/10/16 Python
HTML5新特性之用SVG绘制微信logo
2016/02/03 HTML / CSS
草莓网化妆品日本站:Strawberrynet日本
2017/10/20 全球购物
金蝶的一道SQL笔试题
2012/12/18 面试题
学前教育教师求职自荐信
2013/09/22 职场文书
入党申请人的自我鉴定
2013/12/01 职场文书
通信工程专业毕业生推荐信
2013/12/25 职场文书
文明礼仪伴我行演讲稿
2014/05/12 职场文书
邮政竞聘演讲稿
2014/09/03 职场文书
2015年试用期工作总结
2014/12/12 职场文书
谁动了我的奶酪读书笔记
2015/06/30 职场文书
学校财务管理制度
2015/08/04 职场文书
《初涉尘世》读后感3篇
2020/01/10 职场文书
详解Python函数print用法
2021/06/18 Python