加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php查询ip所在地的方法介绍

发布时间:2022-07-26 05:16:43 所属栏目:PHP教程 来源:互联网
导读:具体实现方法如下: 代码如下:?php /** *@ date 2010.12.21 注:文件头 [第一条索引的偏移量 (4byte)] + [最后一条索引的偏移地址 (4byte)] 8字节 记录区 [结束ip (4byte)] + [地区1] + [地区2] 4字节+不定长 索引区 [开始ip (4byte)] + [指向记录区的偏移
  具体实现方法如下:
 
  代码如下:<?php
  /**
  *@ date         2010.12.21
  注:文件头 [第一条索引的偏移量 (4byte)] + [最后一条索引的偏移地址 (4byte)]     8字节
  记录区 [结束ip (4byte)] + [地区1] + [地区2]                                4字节+不定长
  索引区 [开始ip (4byte)] + [指向记录区的偏移地址 (3byte)]                   7字节
  */
  class iplocation{
  var $fp;
  var $firstip;  //第一条ip索引的偏移地址
  var $lastip;   //最后一条ip索引的偏移地址
  var $totalip;  //总ip数
  /*
  |----------------------------------------------------------------------------
  | 构造函数,初始化一些变量
  |----------------------------------------------------------------------------
  |
  */
  function iplocation($datfile = "qqwry.dat"){
  $this->fp=fopen($datfile,'rb')or die("qqwry.dat不存在,请去网上 <a href='http://www.jb51.net/softs/10529.html'>下载纯真ip数据 库</a>, 'qqwry.dat' 放到当前目录下");   //二制方式打开
  $this->firstip = $this->get4b(); //第一条ip索引的绝对偏移地址
  $this->lastip = $this->get4b();  //最后一条ip索引的绝对偏移地址
  $this->totalip =($this->lastip - $this->firstip)/7 ; //ip总数 索引区是定长的7个字节,在此要除以7,
  register_shutdown_function(array($this,"closefp"));  //为了兼容php5以下版本,本类没有用析构函数,自动关闭ip库.
  }
  /*
  |----------------------------------------------------------------------------
  | 关闭ip库
  |----------------------------------------------------------------------------
  |
  */
  function closefp(){
  fclose($this->fp);
  }
  /*
  |----------------------------------------------------------------------------
  | 读取4个字节并将解压成long的长模式
  |----------------------------------------------------------------------------
  |
  */
  function get4b(){
  $str=unpack("v",fread($this->fp,4));
  return $str[1];
  }
  /*
  |----------------------------------------------------------------------------
  | 读取重定向了的偏移地址
  |----------------------------------------------------------------------------
  |
  */
  function getoffset(){
  $str=unpack("v",fread($this->fp,3).chr(0));
  return $str[1];
  }
  /*
  |----------------------------------------------------------------------------
  | 读取ip的详细地址信息
  php查询ip所在地的方法介绍
       |----------------------------------------------------------------------------
  |
  */
  function getstr(){
  $split=fread($this->fp,1);
  while (ord($split)!=0) {
  $str .=$split;
  $split=fread($this->fp,1);
  }
  return $str;
  }
  /*
  |----------------------------------------------------------------------------
  | 将ip通过ip2long转成ipv4的互联网地址,再将他压缩成big-endian字节序 ,用来和索引区内的ip地址做比较
  |----------------------------------------------------------------------------
  |
  */
  function iptoint($ip){
  return pack("n",intval(ip2long($ip)));
  }
  /*
  |----------------------------------------------------------------------------
  | 获取地址信息
  |----------------------------------------------------------------------------
  |
  */
  function readaddress(){
  $now_offset=ftell($this->fp); //得到当前的指针位址
  $flag=$this->getflag();
  switch (ord($flag)){
  case 0:
  $address="";
  break;
  case 1:
  case 2:
  fseek($this->fp,$this->getoffset());
  $address=$this->getstr();
  break;
  default:
  fseek($this->fp,$now_offset);
  $address=$this->getstr();
  break;
  }
  return $address;
  }
  /*
  |----------------------------------------------------------------------------
  | 获取标志1或2   用来确定地址是否重定向了
  |----------------------------------------------------------------------------
  |
  */
  function getflag(){
  return fread($this->fp,1);
  }
  /*
  |----------------------------------------------------------------------------
  | 用二分查找法在索引区内搜索ip
  |----------------------------------------------------------------------------
  |
  */
  function searchip($ip){
  $ip=gethostbyname($ip);     //将域名转成ip
  $ip_offset["ip"]=$ip;
  $ip=$this->iptoint($ip);    //将ip转换成长整型
  $firstip=0;                 //搜索的上边界
  $lastip=$this->totalip;     //搜索的下边界
  $ipoffset=$this->lastip;    //初始化为最后一条ip地址的偏移地址
  while ($firstip <= $lastip){
  $i=floor(($firstip + $lastip) / 2);          //计算近似中间记录 floor函数记算给定浮点数小的最大整数,说白了就是四舍五也舍
  fseek($this->fp,$this->firstip + $i * 7);    //定位指针到中间记录
  $startip=strrev(fread($this->fp,4));         //读取当前索引区内的开始ip地址,并将其little-endian的字节序转换成big-endian的字节序
  if ($ip < $startip) {
  $lastip=$i - 1;
  }
  else {
  fseek($this->fp,$this->getoffset());
  $endip=strrev(fread($this->fp,4));
  if ($ip > $endip){
  $firstip=$i + 1;
  }
  else {
  $ip_offset["offset"]=$this->firstip + $i * 7;
  break;
  }
  }
  }
  return $ip_offset;
  }
  /*
  |----------------------------------------------------------------------------
  | 获取ip地址详细信息
  |----------------------------------------------------------------------------
  |
  */
  function getaddress($ip){
  $ip_offset=$this->searchip($ip);  //获取ip 在索引区内的绝对编移地址
  $ipoffset=$ip_offset["offset"];
  $address["ip"]=$ip_offset["ip"];
  fseek($this->fp,$ipoffset);      //定位到索引区
  $address["startip"]=long2ip($this->get4b()); //索引区内的开始ip 地址
  $address_offset=$this->getoffset();            //获取索引区内ip在ip记录区内的偏移地址
  fseek($this->fp,$address_offset);            //定位到记录区内
  $address["endip"]=long2ip($this->get4b());   //记录区内的结束ip 地址
  $flag=$this->getflag();                      //读取标志字节
  switch (ord($flag)) {
  case 1:  //地区1地区2都重定向
  $address_offset=$this->getoffset();   //读取重定向地址
  fseek($this->fp,$address_offset);     //定位指针到重定向的地址
  $flag=$this->getflag();               //读取标志字节
  switch (ord($flag)) {
  case 2:  //地区1又一次重定向,
  fseek($this->fp,$this->getoffset());
  $address["area1"]=$this->getstr();
  fseek($this->fp,$address_offset+4);      //跳4个字节
  $address["area2"]=$this->readaddress();  //地区2有可能重定向,有可能没有
  break;
  default: //地区1,地区2都没有重定向
  fseek($this->fp,$address_offset);        //定位指针到重定向的地址
  $address["area1"]=$this->getstr();
  $address["area2"]=$this->readaddress();
  break;
  }
  break;
  case 2: //地区1重定向 地区2没有重定向
  $address1_offset=$this->getoffset();   //读取重定向地址
  fseek($this->fp,$address1_offset);  
  $address["area1"]=$this->getstr();
  fseek($this->fp,$address_offset+8);
  $address["area2"]=$this->readaddress();
  break;
  default: //地区1地区2都没有重定向
  fseek($this->fp,$address_offset+4);
  $address["area1"]=$this->getstr();
  $address["area2"]=$this->readaddress();
  break;
  }
  //*过滤一些无用数据
  if (strpos($address["area1"],"cz88.net")!=false){
  $address["area1"]="未知";
  }
  if (strpos($address["area2"],"cz88.net")!=false){
  $address["area2"]=" ";
  }
  return $address;
  }
  }

  /*用法如下:*/
  $ip=new iplocation("qqwry.dat");
  $address=$ip->getaddress("61.129.51.27");
  //$address=$ip->getaddress(www.jb51.net);
  echo '<pre>';
  print_r($address);
  ?>。

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读