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 相关文章推荐
Dedecms V3.1 生成HTML速度的优化办法
Mar 18 PHP
php防攻击代码升级版
Dec 29 PHP
php学习笔记 php中面向对象三大特性之一[封装性]的应用
Jun 13 PHP
php设计模式 Delegation(委托模式)
Jun 26 PHP
php数组函数序列之array_unshift() 在数组开头插入一个或多个元素
Nov 07 PHP
ThinkPHP框架实现session跨域问题的解决方法
Jul 01 PHP
php实现给图片加灰色半透明效果的方法
Oct 20 PHP
如何使用Gitblog和Markdown建自己的博客
Jul 31 PHP
yii2.0整合阿里云oss的示例代码
Sep 19 PHP
Codeigniter里的无刷新上传的实现代码
Apr 14 PHP
php 多继承的几种常见实现方法示例
Nov 18 PHP
关于Laravel参数验证的一些疑与惑
Nov 19 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使用curl出现Expect:100-continue解决方法
2015/03/03 PHP
CodeIgniter钩子用法实例详解
2016/01/20 PHP
实例讲解PHP设计模式编程中的简单工厂模式
2016/02/29 PHP
Python中使用django form表单验证的方法
2017/01/16 PHP
javascript使用正则获取url上的某个参数
2014/09/04 Javascript
JavaScript弹出新窗口后向父窗口输出内容的方法
2015/04/06 Javascript
jQuery仿天猫实现超炫的加入购物车
2015/05/04 Javascript
Augularjs-起步详解
2016/07/08 Javascript
jQuery的ready方法实现原理分析
2016/10/26 Javascript
vue中使用heatmapjs的示例代码(结合百度地图)
2018/09/05 Javascript
JQuery animate动画应用示例
2019/05/14 jQuery
JavaScript 继承 封装 多态实现及原理详解
2019/07/29 Javascript
vue-cli3项目打包后自动化部署到服务器的方法
2020/09/16 Javascript
[00:52]玛尔斯技能全介绍
2019/03/06 DOTA
Python发送邮件测试报告操作实例详解
2018/12/08 Python
浅析Python 引号、注释、字符串
2019/07/25 Python
在macOS上搭建python环境的实现方法
2019/08/13 Python
Pycharm安装并配置jupyter notebook的实现
2020/05/18 Python
利用scikitlearn画ROC曲线实例
2020/07/02 Python
IE10 Error.stack 让脚本调试更加方便快捷
2013/04/22 HTML / CSS
德国体育用品网上商店:SC24.com
2016/08/01 全球购物
美国领先的水果篮送货公司和新鲜水果供应商:The Fruit Company
2018/02/13 全球购物
视光学专业毕业生推荐信
2013/10/28 职场文书
机械专业毕业生自荐信
2013/11/02 职场文书
探矿工程师自荐信
2014/01/24 职场文书
2014年六一儿童节演讲稿
2014/05/23 职场文书
2014年科技工作总结
2014/11/26 职场文书
公务员考察材料
2014/12/23 职场文书
青岛导游词
2015/02/12 职场文书
2015年新农村建设工作总结
2015/05/22 职场文书
2016继续教育研修日志
2015/11/13 职场文书
个人的事迹材料怎么写
2019/04/24 职场文书
Django如何与Ajax交互
2021/04/29 Python
MySQL 百万级数据的4种查询优化方式
2021/06/07 MySQL
解决persistence.xml配置文件修改存放路径的问题
2022/02/24 Java/Android
聊聊mysql都有哪几种分区方式
2022/04/13 MySQL