<?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. POJ_1061_扩展欧几里德

    青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 107027   Accepted: 21321 Descript ...

  2. 什么是Capability

    desired capability的功能是配置Appium会话.他们告诉Appium服务器您想要自动化的平台和应用程序. Desired Capabilities是一组设置的键值对的集合,其中键对应 ...

  3. TensorFlow实战笔记(17)---TFlearn

    目录: 分布式Estimator 自定义模型 建立自己的机器学习Estimator 调节RunConfig运行时的参数 Experiment和LearnRunner 深度学习Estimator 深度神 ...

  4. [luogu4799 CEOI2015 Day2] 世界冰球锦标赛(折半搜索)

    传送门 Solution 折半搜索裸题,注意\(long long\) Code #include <cmath> #include <cstdio> #include < ...

  5. Visible Trees

    Visible Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Pr ...

  6. mysql explain介绍

    mysql环境优化: 1.如果order by 没有利用到索引,那么将会出现fileSort,如果sort_buffer不够大,fileSort过程则需要使用临时文件 ,fileSort优化,主要通过 ...

  7. js 元素遍历

    2018-06-26 //百度首页测试 var i, len = 0, element = document.querySelector('#s_form_wrapper'), child = ele ...

  8. Spring MVC-表单(Form)标签-多行文本框(TextArea)示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_textarea.htm 说明:示例基于Spring MVC 4.1.6. 以下示 ...

  9. LeetCode之RemoveElement

    题目: Given an array and a value, remove all instances of that value in place and return the new lengt ...

  10. Dynamics CRM 2015 New Feature (9): Services Changes

    Dynamics CRM 2015 为开发者加入了一些新的Service Request以及一个帮助类库XrmTooling,它支持连接各种环境下的CRM,比方:Online,O365,On Prem ...