<?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. ViewPager循环滚动

    一.先写个适配器 public class MyPagerAdapter extends PagerAdapter { /** * 上下文 */ private Context context; /* ...

  2. 省市区县的sql语句——区县

    DROP TABLE IF EXISTS `area`; CREATE TABLE `area` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `code` va ...

  3. List 练习

    (List)已知有一个Worker 类如下: public class Worker { private int age; private String name; private double sa ...

  4. JavaScript图片轮播,举一反三

    图片轮播,在一些购物网站上运用的不胜枚举,下面简单介绍一下图片轮播的实现. 如图 <!doctype html> <html lang="en"> < ...

  5. Memcached 之增删改查命令

    memcache是高性能 ,分布式的内存对象缓存系统,非关系型数据库. 一.增 语法:add  key  flag  expire  length key:值的一个名字 flag:一个标志,是一个正整 ...

  6. 【转载】MySQL之CONCAT()的用法

    mysql CONCAT()函数用于将多个字符串连接成一个字符串,是最重要的mysql函数之一,下面就将为您详细介绍mysql CONCAT()函数,供您参考 mysql CONCAT(str1,st ...

  7. 系统和帮助-Linux基础知识

    iOS镜像: 硬盘分区:留出一些空间;实在不成,可安装完成以后,新增一块虚拟硬盘; 终端:terminal 用户界面: GUI:图形界面 GNome KDE CLI: bash,zsh,sh,csh, ...

  8. COOKIE, SESSION, JSESSION

    http://www.360doc.com/content/11/1027/10/7472437_159535413.shtml

  9. 2、在1.VMware虚拟机上安装ubantu系统

    1.新建新的虚拟机系统 2.使用自定义高级安装 3.选择下一步操作 4.选择稍后安装 4.因为我们要安装的是Linux的发行版本ubuntu,所以这里选择Linux(L),版本是Ubuntu 64位, ...

  10. fastadmin 接口(上传)

    /** * 添加注释指南 * */ public function store(Request $request) { dump($request);exit; $name = $request-&g ...