当前位置:首页 > PHP教程 > php应用 > 列表

php查询ip所在地的方法

发布:smiling 来源: PHP粉丝网  添加日期:2021-05-02 21:28:02 浏览: 评论:0 

这篇文章主要介绍了php查询ip所在地的方法,涉及对纯真ip数据库的实用,是非常常见的实用技巧,需要的朋友可以参考下,本文实例讲述了php查询ip所在地的方法。分享给大家供大家参考。

具体实现方法如下:

  1. /** 
  2. *@ date         2010.12.21 
  3. 注:文件头 [第一条索引的偏移量 (4byte)] + [最后一条索引的偏移地址 (4byte)]     8字节 
  4. 记录区 [结束ip (4byte)] + [地区1] + [地区2]                                4字节+不定长 
  5. 索引区 [开始ip (4byte)] + [指向记录区的偏移地址 (3byte)]                   7字节 
  6. */ 
  7. class iplocation{ 
  8. var $fp; 
  9. var $firstip;  //第一条ip索引的偏移地址 
  10. var $lastip;   //最后一条ip索引的偏移地址 
  11. var $totalip;  //总ip数 
  12. /* 
  13. |---------------------------------------------------------------------------- 
  14. | 构造函数,初始化一些变量 
  15. |---------------------------------------------------------------------------- 
  16. | 
  17. */ 
  18. function iplocation($datfile = "qqwry.dat"){ 
  19. $this->fp=fopen($datfile,'rb')or die("qqwry.dat不存在,请去网上 下载纯真ip数据 库, 'qqwry.dat' 放到当前目录下");   //二制方式打开 
  20. $this->firstip = $this->get4b(); //第一条ip索引的绝对偏移地址 
  21. $this->lastip = $this->get4b();  //最后一条ip索引的绝对偏移地址 
  22. $this->totalip =($this->lastip - $this->firstip)/7 ; //ip总数 索引区是定长的7个字节,在此要除以7, 
  23. register_shutdown_function(array($this,"closefp"));  //为了兼容php5以下版本,本类没有用析构函数,自动关闭ip库. 
  24. } 
  25. /* 
  26. |---------------------------------------------------------------------------- 
  27. | 关闭ip库 
  28. |---------------------------------------------------------------------------- 
  29. | 
  30. */ 
  31. function closefp(){ 
  32. fclose($this->fp); 
  33. } 
  34. /* 
  35. |---------------------------------------------------------------------------- 
  36. | 读取4个字节并将解压成long的长模式 
  37. |---------------------------------------------------------------------------- 
  38. | 
  39. */ 
  40. function get4b(){ 
  41. $str=unpack("v",fread($this->fp,4)); 
  42. return $str[1]; 
  43. } 
  44. /* 
  45. |---------------------------------------------------------------------------- 
  46. | 读取重定向了的偏移地址 
  47. |---------------------------------------------------------------------------- 
  48. | 
  49. */ 
  50. function getoffset(){ 
  51. $str=unpack("v",fread($this->fp,3).chr(0)); 
  52. return $str[1]; 
  53. } 
  54. /* 
  55. |---------------------------------------------------------------------------- 
  56. | 读取ip的详细地址信息 
  57. |---------------------------------------------------------------------------- 
  58. | 
  59. */ 
  60. function getstr(){ 
  61. $split=fread($this->fp,1); 
  62. while (ord($split)!=0) { 
  63. $str .=$split; 
  64. $split=fread($this->fp,1); 
  65. } 
  66. return $str; 
  67. } 
  68. /* 
  69. |---------------------------------------------------------------------------- 
  70. | 将ip通过ip2long转成ipv4的互联网地址,再将他压缩成big-endian字节序 ,用来和索引区内的ip地址做比较 
  71. |---------------------------------------------------------------------------- 
  72. | 
  73. */ 
  74. function iptoint($ip){ 
  75. return pack("n",intval(ip2long($ip))); 
  76. } 
  77. /* 
  78. |---------------------------------------------------------------------------- 
  79. | 获取地址信息 
  80. |---------------------------------------------------------------------------- 
  81. | 
  82. */ 
  83. function readaddress(){ 
  84. $now_offset=ftell($this->fp); //得到当前的指针位址 
  85. $flag=$this->getflag(); 
  86. switch (ord($flag)){ 
  87. case 0: 
  88. $address=""; 
  89. break; 
  90. case 1: 
  91. case 2: 
  92. fseek($this->fp,$this->getoffset()); 
  93. $address=$this->getstr(); 
  94. break; 
  95. default: 
  96. fseek($this->fp,$now_offset); 
  97. $address=$this->getstr(); 
  98. break; 
  99. } 
  100. return $address; 
  101. } 
  102. /* 
  103. |---------------------------------------------------------------------------- 
  104. | 获取标志1或2   用来确定地址是否重定向了 
  105. |---------------------------------------------------------------------------- 
  106. | 
  107. */ 
  108. function getflag(){ 
  109. return fread($this->fp,1); 
  110. } 
  111. /* 
  112. |---------------------------------------------------------------------------- 
  113. | 用二分查找法在索引区内搜索ip 
  114. |---------------------------------------------------------------------------- 
  115. | 
  116. */ 
  117. function searchip($ip){ 
  118. $ip=gethostbyname($ip);     //将域名转成ip 
  119. $ip_offset["ip"]=$ip; 
  120. $ip=$this->iptoint($ip);    //将ip转换成长整型 
  121. $firstip=0;                 //搜索的上边界 
  122. $lastip=$this->totalip;     //搜索的下边界 
  123. $ipoffset=$this->lastip;    //初始化为最后一条ip地址的偏移地址 
  124. while ($firstip <= $lastip){ 
  125. $i=floor(($firstip + $lastip) / 2);          //计算近似中间记录 floor函数记算给定浮点数小的最大整数,说白了就是四舍五也舍 
  126. fseek($this->fp,$this->firstip + $i * 7);    //定位指针到中间记录 
  127. $startip=strrev(fread($this->fp,4));         //读取当前索引区内的开始ip地址,并将其little-endian的字节序转换成big-endian的字节序 
  128. if ($ip < $startip) { 
  129. $lastip=$i - 1; 
  130. } 
  131. else { 
  132. fseek($this->fp,$this->getoffset()); 
  133. $endip=strrev(fread($this->fp,4)); 
  134. if ($ip > $endip){ 
  135. $firstip=$i + 1; 
  136. } 
  137. else { 
  138. $ip_offset["offset"]=$this->firstip + $i * 7; 
  139. break; 
  140. } 
  141. } 
  142. } 
  143. return $ip_offset; 
  144. } 
  145. /* 
  146. |---------------------------------------------------------------------------- 
  147. | 获取ip地址详细信息 
  148. |---------------------------------------------------------------------------- 
  149. | 
  150. */ 
  151. function getaddress($ip){ 
  152. $ip_offset=$this->searchip($ip);  //获取ip 在索引区内的绝对编移地址 
  153. $ipoffset=$ip_offset["offset"]; 
  154. $address["ip"]=$ip_offset["ip"]; 
  155. fseek($this->fp,$ipoffset);      //定位到索引区 
  156. $address["startip"]=long2ip($this->get4b()); //索引区内的开始ip 地址 
  157. $address_offset=$this->getoffset();            //获取索引区内ip在ip记录区内的偏移地址 
  158. fseek($this->fp,$address_offset);            //定位到记录区内 
  159. $address["endip"]=long2ip($this->get4b());   //记录区内的结束ip 地址 
  160. $flag=$this->getflag();                      //读取标志字节 
  161. switch (ord($flag)) { 
  162. case 1:  //地区1地区2都重定向 
  163. $address_offset=$this->getoffset();   //读取重定向地址 
  164. fseek($this->fp,$address_offset);     //定位指针到重定向的地址 
  165. $flag=$this->getflag();               //读取标志字节 
  166. switch (ord($flag)) { 
  167. case 2:  //地区1又一次重定向, 
  168. fseek($this->fp,$this->getoffset()); 
  169. $address["area1"]=$this->getstr(); 
  170. fseek($this->fp,$address_offset+4);      //跳4个字节 
  171. $address["area2"]=$this->readaddress();  //地区2有可能重定向,有可能没有 
  172. break; 
  173. default: //地区1,地区2都没有重定向 
  174. fseek($this->fp,$address_offset);        //定位指针到重定向的地址 
  175. $address["area1"]=$this->getstr(); 
  176. $address["area2"]=$this->readaddress(); 
  177. break; 
  178. } 
  179. break; 
  180. case 2: //地区1重定向 地区2没有重定向 
  181. $address1_offset=$this->getoffset();   //读取重定向地址 
  182. fseek($this->fp,$address1_offset);   
  183. $address["area1"]=$this->getstr(); 
  184. fseek($this->fp,$address_offset+8); 
  185. $address["area2"]=$this->readaddress(); 
  186. break; 
  187. default: //地区1地区2都没有重定向 
  188. fseek($this->fp,$address_offset+4); 
  189. $address["area1"]=$this->getstr(); 
  190. $address["area2"]=$this->readaddress(); 
  191. break; 
  192. } 
  193. //*过滤一些无用数据 
  194. if (strpos($address["area1"],"cz88.net")!=false){ 
  195. $address["area1"]="未知"; 
  196. } 
  197. if (strpos($address["area2"],"cz88.net")!=false){ 
  198. $address["area2"]=" "; 
  199. } 
  200. return $address; 
  201. } 
  202. } 
  203.  
  204. /*用法如下:*/ 
  205. $ip=new iplocation("qqwry.dat"); 
  206. $address=$ip->getaddress("61.129.51.27"); 
  207. //$address=$ip->getaddress(www.phpfensi.com); 
  208. echo '
    '; 
  209. print_r($address); 
  210. ?> 

希望本文所述对大家的PHP程序设计有所帮助。

Tags: php查询ip

分享到: