PHP读取纯真IP数据库的函数

2024-02-29 18:32

本文主要是介绍PHP读取纯真IP数据库的函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Discuz  5.0 不在使用自己的IP数据,而是使用纯真IP的数据格式, 存取纯真IP数据库稍微有点麻烦,它的存储格式比较特殊也很有趣,具体的格式分析参考下面两个链接,其他语言实现参考文章末的链接。

《纯真IP数据库格式详解》
链接一:http://blog.csdn.Net/heiyeshuwu/archive/2006/05/12/725675.aspx
链接二:http://lumaqq.Linuxsir.org/article/qqwry_format_detail.html

纯真IP数据库官网:http://www.cz88.Net/ip/
纯真IP数据库下载:http://update.cz88.Net/soft/qqwry.rar

 

以下函数conrvertip()位于 Discuz!5_GBK/upload/include/misc.func.Php 路径中,有兴趣可以具体去阅读分析。(下面代码我做了简单的修改,更便于阅读,核心没有修改)

 

<?
// ===================================
//
// 功能:IP地址获取真实地址函数
// 参数:$ip - IP地址
// 作者:[Discuz!] (C) Comsenz Inc.
//
//===================================

function  convertip( $ip ) {
    
// IP数据文件路径
     $dat_path   =   ' QQWry.Dat ' ;

    
// 检查IP地址
     if ( ! preg_match ( " /^d{1,3}.d{1,3}.d{1,3}.d{1,3}$/ " ,   $ip )) {
        
return   ' IP Address Error ' ;
    }
    
// 打开IP数据文件
     if ( ! $fd   =  @ fopen ( $dat_path ,   ' rb ' )){
        
return   ' IP date file not exists or access denied ' ;
    }

    
// 分解IP进行运算,得出整形数
     $ip   =   explode ( ' . ' ,   $ip );
    
$ipNum   =   $ip [ 0 *   16777216   +   $ip [ 1 *   65536   +   $ip [ 2 *   256   +   $ip [ 3 ];

    
// 获取IP数据索引开始和结束位置
     $DataBegin   =   fread ( $fd ,   4 );
    
$DataEnd   =   fread ( $fd ,   4 );
    
$ipbegin   =   implode ( '' ,   unpack ( ' L ' ,   $DataBegin ));
    
if ( $ipbegin   <   0 $ipbegin   +=   pow ( 2 ,   32 );
    
$ipend   =   implode ( '' ,   unpack ( ' L ' ,   $DataEnd ));
    
if ( $ipend   <   0 $ipend   +=   pow ( 2 ,   32 );
    
$ipAllNum   =  ( $ipend   -   $ipbegin /   7   +   1 ;
    
    
$BeginNum   =   0 ;
    
$EndNum   =   $ipAllNum ;

    
// 使用二分查找法从索引记录中搜索匹配的IP记录
     while ( $ip1num > $ipNum   ||   $ip2num < $ipNum ) {
        
$Middle =   intval (( $EndNum   +   $BeginNum /   2 );

        
// 偏移指针到索引位置读取4个字节
         fseek ( $fd ,   $ipbegin   +   7   *   $Middle );
        
$ipData1   =   fread ( $fd ,   4 );
        
if ( strlen ( $ipData1 <   4 ) {
            
fclose ( $fd );
            
return   ' System Error ' ;
        }
        
// 提取出来的数据转换成长整形,如果数据是负数则加上2的32次幂
         $ip1num   =   implode ( '' ,   unpack ( ' L ' ,   $ipData1 ));
        
if ( $ip1num   <   0 $ip1num   +=   pow ( 2 ,   32 );
        
        
// 提取的长整型数大于我们IP地址则修改结束位置进行下一次循环
         if ( $ip1num   >   $ipNum ) {
            
$EndNum   =   $Middle ;
            
continue ;
        }
        
        
// 取完上一个索引后取下一个索引
         $DataSeek   =   fread ( $fd ,   3 );
        
if ( strlen ( $DataSeek <   3 ) {
            
fclose ( $fd );
            
return   ' System Error ' ;
        }
        
$DataSeek   =   implode ( '' ,   unpack ( ' L ' ,   $DataSeek . chr ( 0 )));
        
fseek ( $fd ,   $DataSeek );
        
$ipData2   =   fread ( $fd ,   4 );
        
if ( strlen ( $ipData2 <   4 ) {
            
fclose ( $fd );
            
return   ' System Error ' ;
        }
        
$ip2num   =   implode ( '' ,   unpack ( ' L ' ,   $ipData2 ));
        
if ( $ip2num   <   0 $ip2num   +=   pow ( 2 ,   32 );

        
// 没找到提示未知
         if ( $ip2num   <   $ipNum ) {
            
if ( $Middle   ==   $BeginNum ) {
                
fclose ( $fd );
                
return   ' Unknown ' ;
            }
            
$BeginNum   =   $Middle ;
        }
    }

    
// 下面的代码读晕了,没读明白,有兴趣的慢慢读
     $ipFlag   =   fread ( $fd ,   1 );
    
if ( $ipFlag   ==   chr ( 1 )) {
        
$ipSeek   =   fread ( $fd ,   3 );
        
if ( strlen ( $ipSeek <   3 ) {
            
fclose ( $fd );
            
return   ' System Error ' ;
        }
        
$ipSeek   =   implode ( '' ,   unpack ( ' L ' ,   $ipSeek . chr ( 0 )));
        
fseek ( $fd ,   $ipSeek );
        
$ipFlag   =   fread ( $fd ,   1 );
    }

    
if ( $ipFlag   ==   chr ( 2 )) {
        
$AddrSeek   =   fread ( $fd ,   3 );
        
if ( strlen ( $AddrSeek <   3 ) {
            
fclose ( $fd );
            
return   ' System Error ' ;
        }
        
$ipFlag   =   fread ( $fd ,   1 );
        
if ( $ipFlag   ==   chr ( 2 )) {
            
$AddrSeek2   =   fread ( $fd ,   3 );
            
if ( strlen ( $AddrSeek2 <   3 ) {
                
fclose ( $fd );
                
return   ' System Error ' ;
            }
            
$AddrSeek2   =   implode ( '' ,   unpack ( ' L ' ,   $AddrSeek2 . chr ( 0 )));
            
fseek ( $fd ,   $AddrSeek2 );
        } 
else  {
            
fseek ( $fd ,   - 1 ,  SEEK_CUR);
        }

        
while (( $char   =   fread ( $fd ,   1 ))  !=   chr ( 0 ))
            
$ipAddr2   .=   $char ;

        
$AddrSeek   =   implode ( '' ,   unpack ( ' L ' ,   $AddrSeek . chr ( 0 )));
        
fseek ( $fd ,   $AddrSeek );

        
while (( $char   =   fread ( $fd ,   1 ))  !=   chr ( 0 ))
            
$ipAddr1   .=   $char ;
    } 
else  {
        
fseek ( $fd ,   - 1 ,  SEEK_CUR);
        
while (( $char   =   fread ( $fd ,   1 ))  !=   chr ( 0 ))
            
$ipAddr1   .=   $char ;

        
$ipFlag   =   fread ( $fd ,   1 );
        
if ( $ipFlag   ==   chr ( 2 )) {
            
$AddrSeek2   =   fread ( $fd ,   3 );
            
if ( strlen ( $AddrSeek2 <   3 ) {
                
fclose ( $fd );
                
return   ' System Error ' ;
            }
            
$AddrSeek2   =   implode ( '' ,   unpack ( ' L ' ,   $AddrSeek2 . chr ( 0 )));
            
fseek ( $fd ,   $AddrSeek2 );
        } 
else  {
            
fseek ( $fd ,   - 1 ,  SEEK_CUR);
        }
        
while (( $char   =   fread ( $fd ,   1 ))  !=   chr ( 0 )){
            
$ipAddr2   .=   $char ;
        }
    }
    
fclose ( $fd );

    
// 最后做相应的替换操作后返回结果
     if ( preg_match ( ' /http/i ' ,   $ipAddr2 )) {
        
$ipAddr2   =   '' ;
    }
    
$ipaddr   =   " $ipAddr1 $ipAddr2 " ;
    
$ipaddr   =   preg_replace ( ' /CZ88.Net/is ' ,   '' ,   $ipaddr );
    
$ipaddr   =   preg_replace ( ' /^s*/is ' ,   '' ,   $ipaddr );
    
$ipaddr   =   preg_replace ( ' /s*$/is ' ,   '' ,   $ipaddr );
    
if ( preg_match ( ' /http/i ' ,   $ipaddr ||   $ipaddr   ==   '' ) {
        
$ipaddr   =   ' Unknown ' ;
    }

    
return   $ipaddr ;
}


// ========================
//
//  调用举例(速度很快)
//
//========================


echo  convertip( ' 219.238.235.10 ' );
// 输出: 北京市 电信通

echo  convertip( ' 23.56.82.12 ' );
// 输出:IANA

echo  convertip( ' 250.69.52.0 ' );
// 输出:IANA保留地址

echo  convertip( ' 238.69.52.0 ' );
// 输出:IANA保留地址 用于多点传送

echo  convertip( ' 192.168.0.1 ' );
// 输出:局域网 对方和您在同一内部网

echo  convertip( ' 255.255.255.255 ' );
// 输出:纯真网络 2006年11月20日IP数据

?>



附:(相应其他实现程序)

Php)" href="http://www.coolcode.cn/?p=16" rel=bookmark>利用 QQWry.Dat 实现 IP 地址高效检索(Php)(作者: andot)

数据库(QQWry.Dat)查询 C源码" href="http://www.douzi.org/wp/index.Php/articles/71" rel=bookmark>纯真IP数据库(QQWry.Dat)查询 C源码 (作者:Windix)

 

这篇关于PHP读取纯真IP数据库的函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/759667

相关文章

如何使用 Python 读取 Excel 数据

《如何使用Python读取Excel数据》:本文主要介绍使用Python读取Excel数据的详细教程,通过pandas和openpyxl,你可以轻松读取Excel文件,并进行各种数据处理操... 目录使用 python 读取 Excel 数据的详细教程1. 安装必要的依赖2. 读取 Excel 文件3. 读

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

数据库面试必备之MySQL中的乐观锁与悲观锁

《数据库面试必备之MySQL中的乐观锁与悲观锁》:本文主要介绍数据库面试必备之MySQL中乐观锁与悲观锁的相关资料,乐观锁适用于读多写少的场景,通过版本号检查避免冲突,而悲观锁适用于写多读少且对数... 目录一、引言二、乐观锁(一)原理(二)应用场景(三)示例代码三、悲观锁(一)原理(二)应用场景(三)示例

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地