<?php

/**

* IP 地理位置查询类

*

* @author 马秉尧

* @version 1.5

* @copyright 2005 CoolCode.CN

*/

class IpLocation {

     /**

      * QQWry.Dat文件指针

      *

      * @var resource

      */

     var $fp;

     /**

      * 第一条IP记录的偏移地址

      *

      * @var int

      */

     var $firstip;

     /**

      * 最后一条IP记录的偏移地址

      *

      * @var int

      */

     var $lastip;

     /**

      * IP记录的总条数(不包含版本信息记录)

      *

      * @var int

      */

     var $totalip;

     /**

      * 返回读取的长整型数

      *

      * @access private

      * @return int

      */

     function getlong() {

         //将读取的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;

     }

     /**

      * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息

      *

      * @param string $filename

      * @return IpLocation

      */

     function IpLocation($filename ='E:\php_project\test\thinkphp_3.2.2_full\ThinkPHP\Library\Org\Net\UTFWry.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;

     }

}

//test demo
$ip = "202.101.111.195";
$iplocation = new IpLocation();
$location = $iplocation->getlocation($ip);
print_r($location);
?>

UTFWry.dat地址:http://pan.baidu.com/s/1sjQAUcd

下载 UTFWry.dat 放到本地 路径替换  $filename ='E:\php_project\test\thinkphp_3.2.2_full\ThinkPHP\Library\Org\Net\UTFWry.dat'

通过ip获取地址的更多相关文章

  1. 如何根据Ip获取地址信息--Java----待整理完善!!!

    如何根据Ip获取地址信息--Java----待整理完善!!! QQWry.dat数据写入方法: http://www.cnblogs.com/xumingxiang/archive/2013/02/1 ...

  2. java-通过ip获取地址

    添加maven依赖 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all&l ...

  3. C#调用百度高精度IP定位API通过IP获取地址

    API首页:http://lbsyun.baidu.com/index.php?title=webapi/high-acc-ip 1.申请百度账号,创建应用,获取密钥(AK) http://lbsyu ...

  4. PHP 中根据 IP 获取地址

    这里使用的是淘宝 IP 地址库提供的 API 接口. 淘宝 IP 地址库:http://ip.taobao.com/instructions.html API 文档说明:  使用事例: /** * 调 ...

  5. 几种获取IP 根据IP获取地址的方法 JS,第三方 新浪 网易 腾讯

    第一种是利用纯真ip数据库,这个可以在网上找到很多,缺点是更新有点慢. 第二种是利用门户网站的接口 目前已知的有腾讯.新浪.网易.搜狐和Google提供IP地址查询API,但是找得到的只有腾讯.新浪和 ...

  6. Java 根据IP获取地址

    用淘宝接口:(源码:java 根据IP地址获取地理位置) pom.xml: <!-- https://mvnrepository.com/artifact/net.sourceforge.jre ...

  7. python通过ip获取地址

    # -*- coding: utf-8 -*- url = "http://ip.taobao.com/service/getIpInfo.php?ip=" #查找IP地址 def ...

  8. 淘宝IP地址库API接口(PHP)通过ip获取地址信息

    淘宝IP地址库网址:http://ip.taobao.com/ 提供的服务包括: 1. 根据用户提供的IP地址,快速查询出该IP地址所在的地理信息和地理相关的信息,包括国家.省.市和运营商. 2. 用 ...

  9. java获取登录ip和地址

    //获取HttpServletRequest对象 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestCon ...

随机推荐

  1. VM虚拟机中Ubuntu中执行apt-get update失败的解决方法(可能有效)

    首先确保虚拟机是连接网络的,可以用ping命令检测一下看是否连通网络.采用nat网络的时候确保服务是开的. 如果之前执行过apt-get update命令但是失败了,执行一下      rm -rf ...

  2. SQL Server2008优化之SET STATISTICS开关

    一.准备工作 缓存对于某个查询的性能影响十分之大,所以优化之前要清空缓存. 清除Buffer Pool时面的所有缓存 DBCC DROPCLEANBUFFERS清除Buffer Pool里的所有缓存的 ...

  3. Spring Boot 整合mybatis时遇到的mapper接口不能注入的问题

    现实情况是这样的,因为在练习spring boot整合mybatis,所以自己新建了个项目做测试,可是在idea里面mapper接口注入报错,后来百度查询了下,把idea的注入等级设置为了warnin ...

  4. jQuery实现菜单全选/不选

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. ESP32 开发笔记(十二)LittlevGL 添加自定义字体和物理按键

    LittlevGL 添加自定义字体获取字库 ttf 文件可以从一些网站上获取字库文件,比如请注意字体许可证 生成源文件使用 LittlevGL 提供的字库文件转换工具,将 ttf 字库文件转换为源文件 ...

  6. 拓扑排序(Topological Order)

    Date:2019-06-17 14:43:59 算法描述 1.定义队列Q,并把所有入度为0的结点加入队列 2.取队首结点,输出.然后删除所有从它除法的边,并令这些边到达的顶点的入度-1,若某个顶点的 ...

  7. Scrapy处理200-300范围之外的响应代码

    HttpErrorMiddleware 类scrapy.spidermiddlewares.httperror.HttpErrorMiddleware 过滤掉不成功(错误)的HTTP响应,以便蜘蛛不必 ...

  8. JavaScript、Dom和jQuery

    var obj=document.getElementById('t1') obj.innerText obj.innerHTML 1.javascript 插入代码如下: <script ty ...

  9. 58.fetch phbase

    1.fetch phbase工作流程 The coordinating node identifies which documents need to be fetched and issues a ...

  10. 从零开始创建一个 PHP 扩展

    创建一个扩展的基本步骤都有哪些.示例中,我们将实现如下功能: <?phpecho say();?> 输出内容: $ php ./test.php$ hello word 在扩展中实现一个s ...