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

相关文章

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

如何通过try-catch判断数据库唯一键字段是否重复

《如何通过try-catch判断数据库唯一键字段是否重复》在MyBatis+MySQL中,通过try-catch捕获唯一约束异常可避免重复数据查询,优点是减少数据库交互、提升并发安全,缺点是异常处理开... 目录1、原理2、怎么理解“异常走的是数据库错误路径,开销比普通逻辑分支稍高”?1. 普通逻辑分支 v

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

使用shardingsphere实现mysql数据库分片方式

《使用shardingsphere实现mysql数据库分片方式》本文介绍如何使用ShardingSphere-JDBC在SpringBoot中实现MySQL水平分库,涵盖分片策略、路由算法及零侵入配置... 目录一、ShardingSphere 简介1.1 对比1.2 核心概念1.3 Sharding-Sp

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N