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
在Windows版的PHP中使用ADO
Oct 09 PHP
require(),include(),require_once()和include_once()区别
Mar 27 PHP
PHP伪静态写法附代码
Jun 20 PHP
有关php运算符的知识大全
Nov 03 PHP
解析php中反射的应用
Jun 18 PHP
php将数组转换成csv格式文件输出的方法
Mar 14 PHP
php邮件发送的两种方式
Apr 28 PHP
PHP转换文本框内容为HTML格式的方法
Jul 20 PHP
PHP获取访问页面HTTP状态码的实现代码
Nov 03 PHP
php观察者模式应用场景实例详解
Feb 03 PHP
php实现微信企业转账功能
Oct 02 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
pdo中使用参数化查询sql
2011/08/11 PHP
php返回当前日期或者指定日期是周几
2015/05/21 PHP
PHP自带方法验证邮箱是否存在
2016/02/01 PHP
PHP使用glob方法遍历文件夹下所有文件的实例
2018/10/17 PHP
YII框架学习笔记之命名空间、操作响应与视图操作示例
2019/04/30 PHP
KindEditor在php环境下上传图片功能集成的方法示例
2020/07/20 PHP
JavaScript中Math对象使用说明
2008/01/16 Javascript
jquery实现背景墙聚光灯效果示例分享
2014/03/02 Javascript
jQuery $命名冲突解决方案汇总
2014/11/13 Javascript
AngularJS + Node.js + MongoDB开发的基于高德地图位置的通讯录
2015/01/02 Javascript
javascript实现判断鼠标的状态
2015/07/10 Javascript
innerHTML中标签可以换行的方法汇总
2015/08/14 Javascript
js 判断一组日期是否是连续的简单实例
2016/07/11 Javascript
JavaScript实现的原生态Tab标签页功能【兼容IE6】
2017/09/18 Javascript
关于axios不能使用Vue.use()浅析
2018/01/12 Javascript
vue回到顶部监听滚动事件详解
2019/08/02 Javascript
JS实现音乐导航特效
2020/01/06 Javascript
el-table树形表格表单验证(列表生成序号)
2020/05/31 Javascript
用vue设计一个日历表
2020/12/03 Vue.js
[05:26]2014DOTA2西雅图国际邀请赛 iG战队巡礼
2014/07/07 DOTA
[02:57]DOTA2亚洲邀请赛小组赛第四日 赛事回顾
2015/02/02 DOTA
python获取豆瓣电影简介代码分享
2014/01/16 Python
总结Python中逻辑运算符的使用
2015/05/13 Python
使用Python检测文章抄袭及去重算法原理解析
2019/06/14 Python
python中time.ctime()实例用法
2021/02/03 Python
Html5上传图片 移动端、PC端通用代码
2016/06/08 HTML / CSS
Java模拟试题
2014/11/10 面试题
入党自我鉴定
2014/03/25 职场文书
党员群众路线对照检查材料思想汇报
2014/09/17 职场文书
不服从公司安排检讨书
2014/09/24 职场文书
明星邀请函
2015/02/02 职场文书
2015年三八妇女节活动总结
2015/02/06 职场文书
2015年世界无烟日活动总结
2015/02/10 职场文书
InterProcessMutex实现zookeeper分布式锁原理
2022/03/21 Java/Android
redis复制有可能碰到的问题汇总
2022/04/03 Redis
海弦WR-800F
2022/04/05 无线电