利用纯真版IP数据文件,优化查询方法,提高格式转换效率,减少读取文件的次数,达到快速在线查询IP的目的。大幅度减少文件读取次数,对保护服务器硬盘应该有一定的好处。并增加一个数据库浏览器,可以浏览纯真版QQIP数据文件。 1.用ip2long()做IP校验 <form name="ipform" method="get" action=""> <br/>IP Address:<input type="text" name="ip"/> <br/><a href="javascript:document.ipform.submit();">Submit</a> <br/> </form> <?php define('IPDATA','ipdata.db'); //get ip $ip = isset($_GET['ip'])?$_GET['ip']:getenv("REMOTE_ADDR"); echo "IP: ARIN"; if (-1 === ($ip = ip2long($ip))) die("Invalid IP"); $ip = sprintf("%u",$ip); $country = $city = ''; echo " Record No:".Whois($ip,$country,$city); echo " Location: []"; function Whois($ip,&$country,&$city) { //open ip-database if (NULL == ($fp = fopen(IPDATA, "rb"))) die("cannot open dbfile."); //get data section offset $offset = unpack("Vbegin/Vend", fread($fp, 8)); $begin = 0;$end = ($offset['end'] - $offset['begin']) / 7; //seek index while ($begin < $end - 1) { $num = ($begin + $end) >> 1; fseek ($fp , ($offset['begin'] + $num * 7) , SEEK_SET ) ; $record = unpack("Vip", fread($fp, 4)); $record['ip'] = sprintf("%u",$record['ip']); if ($ip == $record['ip']) { $begin = $num; break;} if ($ip > $record['ip']) $begin = $num; else $end = $num; } //read index $record = unpack("Vbeginip/Vloc", ReadBinary($fp,$offset['begin']+$begin*7) ); $locoff =($record['loc'] & 0x00FFFFFF); $info = unpack("Vendip/Vloc",ReadBinary($fp,$locoff)) ; $info['endip'] = sprintf("%u",$info['endip']); if($info['endip'] < $ip) die(" [unkown location]"); //get GEO $countryoff = (($info['loc'] & 0x000000FF)== 1)?($info['loc'] >> 8):($locoff+4); $country = ReadGEOStr($fp,$countryoff); $city = ReadGEOStr($fp,$countryoff); return $begin; } function ReadGEOStr($fp,&$offset) { $binarydata = ReadBinary($fp,$offset); $info = unpack("Vloc",$binarydata); if( ($info['loc'] & 0x000000FF) == 2 ) { $GeoStr = ReadBinary($fp,$info['loc'] >> 8 ); $GeoStr = substr($GeoStr,0,strpos($GeoStr, 0)); $offset += 4; }else { $len = strpos($binarydata, 0); $GeoStr = substr($binarydata,0,$len); $offset += $len + 1; } return $GeoStr; } function ReadBinary($fp,$positionz) { fseek ( $fp , $positionz , SEEK_SET ) ; return fread ( $fp , 32 ) ; } ?> <form action="" method="get" name="ipform"> IP Address:<input name="ip" type="text"> <a href="javascript:document.ipform.submit();">Submit</a> </form> <form action="" method="get" name="record"> Start<input name="s" type="text"> Count<input name="c" type="text"> <a href="javascript:document.record.submit();">Submit</a> </form> <?php define('IPDATA','ipdata.db'); $fp = NULL; if( isset($_GET['ip']) ) { $ipx = $_GET['ip']; if (-1 === ($ip = ip2long($ipx))) die("Invalid IP"); echo "IP: <a href=\"whoisip.php?ip=\">ARIN</a>"; $ip = sprintf("%u",$ip); $ippostion = ''; $start_time=get_time(); echo "<br>Record No:".Whois($ippostion); $end_time=get_time(); echo "<br>Location:"; echo "<br>Process Time:".round($end_time-$start_time,3)."seconds"; } else if ( isset($_GET['s']) ) { $first = $_GET['s']; $rcount = $_GET['c']; $startoff = $end = 0; GetSection($startoff,$end); if( ($i = $first+$rcount)>$end || $first<0) die ("count overflow"); else { $j = $first-$rcount; echo "<a href='?s=$j&c=$rcount'>Prev</a>:::"; $j = $first+$rcount; echo "<a href='?s=$j&c=$rcount'>Next</a><br>"; } while( $first < $i) { echo ReadRecord($startoff,$first,$startip,$endip); $startip = long2ip($startip); $endip = long2ip($endip); echo " :--<br>"; $first ++; } fclose($fp); } else { echo "Powered by <a href='http://www.eoncn.com'>www.eoncn.com</a>"; } function Whois(&$country) { global $ip,$fp; $startoff = $begin = $end = 0; GetSection($startoff,$end); //seek index while ($begin < $end - 1) { $num = ($begin + $end) >> 1; fseek ($fp , $startoff + $num * 7 , SEEK_SET ) ; $record = unpack("Vip", fread($fp, 4)); $record['ip'] = sprintf("%u",$record['ip']); if ($ip == $record['ip']) { $begin = $num; break;} if ($ip > $record['ip']) $begin = $num; else $end = $num; } //read index $startip = $endip = 0; $country = ReadRecord($startoff,$begin,$startip,$endip); fclose($fp); return $begin; } function GetSection(&$startoff,&$total) { global $fp; //open ip-database if (NULL == ($fp = fopen(IPDATA, "rb"))) die("cannot open dbfile."); //get data section offset $offset = unpack("Vbegin/Vend", fread($fp, 8)); $total = ($offset['end'] - $offset['begin']) / 7; $startoff = $offset['begin']; } function ReadRecord($startoff,$number,&$startip,&$endip) { global $ip; $record = unpack("Vbeginip/Vloc", ReadBinary($startoff+$number*7) ); $startip = $record['beginip']; $locoff =($record['loc'] & 0x00FFFFFF); $info = unpack("Vendip/Vloc",ReadBinary($locoff)) ; $endip = $info['endip']; $info['endip'] = sprintf("%u",$info['endip']); if($info['endip'] < $ip) die(" [unkown location]"); //get GEO $countryoff = (($info['loc'] & 0x000000FF)== 1)?($info['loc'] >> 8):($locoff+4); return ReadGEOStr($countryoff)."->".ReadGEOStr($countryoff); } function ReadGEOStr(&$offset) { $binarydata = ReadBinary($offset); $info = unpack("Vloc",$binarydata); if( ($info['loc'] & 0x000000FF) == 2 ) { $GeoStr = ReadBinary($info['loc'] >> 8 ); $GeoStr = substr($GeoStr,0,strpos($GeoStr, 0)); $offset += 4; }else { $len = strpos($binarydata, 0); $GeoStr = substr($binarydata,0,$len); $offset += $len + 1; } return $GeoStr; } function ReadBinary($positionz) { global $fp; fseek ( $fp , $positionz , SEEK_SET ) ; return fread ( $fp , 32 ) ; } function get_time() { $mtime=microtime(); $mtime=explode(" ",$mtime); $mtime=$mtime[1]+$mtime[0]; return($mtime); } ?> 总结:完成此功能最好将数据导入到数据库,用数据库查询,才能达到最快的速度。 参考数据库查询效果:http://www.eoncn.com首页的IP地址查询。 |