php查询ip所在地代码
<?php /** *@ date 2010.12.21 *@ author 王刚 *@ email 373882774@qq测试数据 *@ qq 373882774 注:文件头 [第一条索引的偏移量 (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://HdhCmsTestheqee测试数据/apps教程/download/iplocationapi.rar'>下载纯真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的详细地址信息 |---------------------------------------------------------------------------- | */ 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( "221.231.102.100" ); //$address=$ip->getaddress(HdhCmsTest111cn.net); echo '<pre>' ; print_r( $address ); ?>查看更多关于php查询ip所在地代码 - php类库的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did29547