背景
在不借助第三方工具的前提下,实现IP高效定位地理位置(这里以ipv6为例子)
设计思路
- 需要将IP转换成一个整数类型
- 根据IP文件(ipv6.txt)生成一个索引文件
- head:存储IP索引的起始偏移量和结束偏移量:起始偏移量和结束偏移量各占4个字节,共8个字节
- data:存储IP的详细信息,长度根据ipv6的具体数据大小决定,结束时用\x00提示
- index:索引信息,起始IP的值(38个字节)和详细信息的位置偏移量(4个字节),共42个字节
- 使用二分查找法对比查找IP和IP文件中的IP范围
- 首先获取head中内容,得到起始和结束索引的位置偏移量
- 然后根据这个偏移量获取到IP的索引位置,加上二分法通过与起始IP对比
- 找到后通过位置偏移量获取到最终地理位置
代码实现
<?php
class Ug_Util_Ipsss {
private $forceReForm = false; // 是否强制重新生成索引文件
private $filename = "/colombo_ipv6lib.txt"; //保存IP地址的文件
private $head = array(); // 0起始IP的文件开始位置,1起始IP的文件结束位置
private $index = array();
private $data = array(); //数据信息的位置
private $start_data_offset = 8; // 起始偏移量
private $index_len = 0; // 索引长度
CONST READ_64bit_OFFSET = 9;
CONST READ_32bit_OFFSET = 5;
CONST EVERY_INDEX_OFFSET = 42;
/**
* @description 初始化文件
* @param $filename
* @param $forceReForm
*/
public function __construct($filename = "", $forceReForm = false)
{
//变量赋值
$this->filename = empty($filename) ? $this->filename : $filename;
$this->forceReForm = $forceReForm;
$this->formatFile = "/ipv6";
//若强制重新生成索引标志为真或者不存在索引文件,则重新生成
if ($this->forceReForm || !file_exists($this->formatFile)) {
$this->ipv6FormatFile();
}
}
/**
* @description 用txt文件生成索引文件
*
*/
private function ipv6FormatFile()
{
//读源文件,写入到新的索引文件
$readfd = fopen($this->filename, 'rb');
$writefd = fopen($this->formatFile.'_tmp', 'wb+');
if ($readfd === false || $writefd === false) {
return false;
}
while (!feof($readfd)