文档章节

纯真IP地址库合并

心驰
 心驰
发布于 2017/09/06 17:19
字数 689
阅读 4
收藏 0
<?php
/**
 * @author( author = 'xbruce' )
 * @datetime( datetime = '2017年7月2日 下午3:29:44' )
 * @comment( comment='ip地址工具' )
 */
class IpUtils
{
    private static $_instance = null;

    private $_nredis = null;
    
    private $arrIpsTmp = array();
    
    const REDIS_SS_IPS = 'l_ss_ips';
    
    const GREP_IP = "/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/";
    
    private function __construct( $redis = null )
    {
        if( $redis )
        {
            $this->_nredis = $redis;
        }

        assert( $redis, 'redis实例不能为空!' );
    }

    static public function getInstance( $redis = null )
    {
        assert( $redis, 'redis实例不能为空!' );
        
        if( !$redis )
        {
            echo 'redis实例不能为空!', PHP_EOL;
            return null;
        }
        
        if( is_null( self::$_instance ) )
        {
            self::$_instance = new IpUtils( $redis );
        }
        
        return self::$_instance;
    }
  
    /**
     * 
     * @author( author='xbruce' )
     * @date( date = '2017年7月2日' )
     * @comment( comment = '读文件到内存中以方便写查询缓存' )
     * @method( method = '' )
     * @op( op = '' )
     * @param string $strFileName
     * @return boolean
     */
    public function initIpLibFromFile( string $strFileName = null )
    {
        set_time_limit( 0 );
        ini_set( 'memory_limit', '1024M' );
        
        if( !file_exists( $strFileName ))
        {
            return false;
        }
        
//         $this->removeSetKeys();
        
        $fIp = fopen( $strFileName, 'r' );
        
        if( !$fIp )
        {
            return false;
        }
                
        echo '正在进行缓存请稍后...' . PHP_EOL;
        $ip = array();
        
        $iIndex = 0;
        while( ($line = trim( fgets( $fIp ))) != '' )
        {
            $line = mb_convert_encoding( $line, 'UTF8', 'GBK' );
            
            preg_match_all( "/[^\s]+/", $line, $arrMatches );
            
            if( count( $arrMatches[0] ) < 3 )
            {
                return false;
            }
            
            $arrIpInfo = $arrMatches[0];
            $ip['ip_begin'] = $this->ip2longCust( $arrIpInfo[0] );
            $ip['ip_end'] = $this->ip2longCust( $arrIpInfo[1] );
            
            $ip['info'] = '';
            $key = $arrIpInfo[2];
            $iInfoCnt = count( $arrIpInfo );
            for( $i = 2; $i < $iInfoCnt; ++$i )
            {
                $ip['info'] .= ' ' . $arrIpInfo[$i];
            }
            
            $strKey = md5( $key );
            
            $this->arrIpsTmp[ $strKey ][$ip['ip_begin']] = $ip;

            unset($ip);
        }
        
        fclose( $fIp );
        
        echo '写缓存结束!' . PHP_EOL;
        
        return true;
    }
    
    /**
     * 
     * @author( author='xbruce' )
     * @date( date = '2017年7月2日' )
     * @comment( comment = '' )
     * @method( method = '' )
     * @op( op = '' )
     */
    public function combineAdjacentIp()
    {
        ini_set( 'memory_limit', '1024M' );
        
        $arrDupIps = array();
        $arrKeys = $this->arrIpsTmp;
        
        $iIndex = 0;
        
        foreach( $arrKeys as $v )
        {     
            $arrIps = $v;
            foreach( $arrIps as $ip )
            {
                $arrDupIps[ $ip['ip_begin'] ] = $ip;
            }
            
            unset( $arrIps );
                        
            if( uksort( $arrDupIps, function( $left, $right ){
                if( $left < $right )
                {
                    return -1;
                }
                else if( $left == $right )
                {
                    return 0;
                }
                else 
                {
                    return 1;
                }
            }))
            {
                $iCnt = 0;
                
                $arrTemp = array();
                foreach( $arrDupIps as $key => $val )
                {
                    $arrTemp[$iCnt++] = $val;
                }
                unset( $arrDupIps );
                
                $iTargetIndex = 0;
                
                $curIp = $arrTemp[0];
                
                if( $iCnt > 1 )
                {
                    for( $i = 0; $i < $iCnt; ++$i )
                    {
                        if( $i + 1 < $iCnt && ( $curIp['ip_end'] + 1 == $arrTemp[ $i + 1 ]['ip_begin'] ))
                        {
                            $curIp['ip_end'] = $arrTemp[ $i + 1 ]['ip_end'];
                        }
                        else 
                        {
                            ++$iIndex;
                            $this->_nredis->zAdd( self::REDIS_SS_IPS, $curIp['ip_begin'], json_encode( $curIp ));
                            
                            if( $i + 1 < $iCnt )
                            {
                                $curIp = $arrTemp[$i+1];
                            }
                        }
                        
                    }
                }
                else if( 1 == $iCnt )
                {
                    $this->_nredis->zAdd( self::REDIS_SS_IPS, $curIp['ip_begin'], json_encode( $curIp ));
                    ++$iIndex;                    
                }

                unset( $arrTargets );
                unset( $arrTemp );
                
                echo '已处理到第', $iIndex, '个', PHP_EOL;
            }
            else
            {
                echo '排序失败,请检查错误原因!', PHP_EOL;
                exit();
            }
            
        }
        
        echo PHP_EOL, '成功精简IP地址库!', PHP_EOL;
    }
    
    
    /**
     * 
     * @author( author='xbruce' )
     * @date( date = '2017年7月2日' )
     * @comment( comment = '取IP地址相关信息' )
     * @method( method = '' )
     * @op( op = '' )
     * @param string $strIp
     */
    public function getIpLocation( string $strIp = null )
    {
        if( empty( $strIp ) || ( $strIp = trim( $strIp )) == '' )
        {
            return false;
        }

        $lIp = $this->ip2longCust( $strIp );

        $r = $this->_nredis->zRevRangeByScore( self::REDIS_SS_IPS, $lIp, -1, array( 'limit' => array( 0, 1 )));
        
        if( count( $r ) >= 1 )
        {
            $objIp = json_decode( $r[0] );
            if( $objIp->ip_begin <= $lIp && $lIp <= $objIp->ip_end )
            {
                return $objIp;
            }
            
            return false;
        }
        
        return false;
    }
    
    
    public function test()
    {
        return $this->getIpLocation( '8.8.8.8');
    }
    
    /**
     * @author( author='xbruce' )
     * @date( date = '2017年7月2日' )
     * @comment( comment = '解决因ip2long bug而引起的bug' )
     * @method( method = '' )
     * @op( op = '' )
     * @param string $strIp
     */
    private function ip2longCust( string $strIp )
    {
        if( preg_match( self::GREP_IP, $strIp ) && is_string( $strIp ) )
        {
            $arrIps = explode( '.', $strIp );
            $strIpTmp = '';
            foreach( $arrIps as $k => $v )
            {
                $strIpTmp .= intval( $v ) . '.';
            }
    
            $strIpTmp = rtrim( $strIpTmp, '\.' );
    
            return ip2long( $strIpTmp );
    
        }
    
        return false;
    }
    
}

// $redis = new Redis();

$redis = new Redis();
$redis->connect( '127.0.0.1', 6379 );
$redis->auth( 'pass' );//redis requirepass
// $redis->select( 0 );

$iu = IpUtils::getInstance( $redis );
// var_dump( $iu->initIpLibFromFile( '/git/phcms/czip.txt' ) );//初始化文件到临时文件
// $iu->combineAdjacentIp();//合并同一地的相邻IP

$t = microtime( true );
for( $i = 0; $i < 100000; ++$i )
{
    $objRes = $iu->test();
}

echo microtime( true ) - $t;
//在我的配置很低小本子上可以达到15190QPS以上

本文转载自:https://my.oschina.net/u/1584951/blog/1114029

共有 人打赏支持
心驰
粉丝 0
博文 21
码字总数 1050
作品 0
海淀
程序员
Java解析归属地,以前用纯真库,现在需要兼容ipv6

之前项目用纯真的ip库,然后写的Java代码查询纯真库中相应ip的归属地,现在项目需要支持ipv6的ip地址,所以归属地查询就是问题,首先 纯真的ipv6版本的数据库去哪里下载? 其次 查询该ipv6的...

bluysky
2013/08/15
317
0
国内常用ip地址库

腾讯腾讯IP分享计划IP分享 新浪http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=8.8.8.8&format=js 百度Web服务Geocoding API-百度地图 淘宝淘宝IP地址库 geoip MaxMind - IP地理定位...

沉淀岁月
2016/07/19
117
0
C# 调用IP库(QQWry.Dat)查询IP位置及自动升级IP库方法(附IP库下载地址及相关dll下载)

前言 C# 用IP地址(123.125.114.144)查询位置(北京市百度公司)的东西,非常好用也非常方便,可手动升级刷新IP库,一次编码永久收益,可支持winform、asp.net等程序。 本文使用的IP库为, ...

王磊的博客
2012/06/01
0
0
高效查询纯真IP库 --lib-qqwry

lib-qqwry是一个高效查询纯真 IP 库(qqwry.dat)的模块。它是用 NodeJS 解析纯真 IP 库(QQwry.dat) ,支持 IP 段查询。为更好的字符转化效率,未使用iconv模块,直接使用gbk编码表文件。经过不...

含浪
2015/05/22
759
0
关于ip识别的问题和ip存储的问题

在登录网站的时间,一些可以直接通过识别ip来显示相应位置的信息。 ip信息在数据库里面是怎么存储的,我看纯真ip库有四十多万的ip地址信息。如果放在一个表里面去匹配的话时间应该会很长,但...

mrmusic
2015/09/25
193
5

没有更多内容

加载失败,请刷新页面

加载更多

Bash各类扩展详解

Bash各类扩展详解 Bash中主要包括大括号扩展、波浪号扩展、变量扩展、子命令扩展、文件名扩展和算数扩展。这些扩展组合在一起为Bash带来了极大的易用性。掌握这些扩展的用法和功能,能够为B...

小陶小陶
38分钟前
1
0
EventBus原理深度解析

一、问题描述 在工作中,经常会遇见使用异步的方式来发送事件,或者触发另外一个动作:经常用到的框架是MQ(分布式方式通知)。如果是同一个jvm里面通知的话,就可以使用EventBus。由于Event...

yangjianzhou
今天
5
0
OpenCV图像处理实例:libuv+cvui显示摄像头视频

#include <iostream>#include <opencv2/opencv.hpp>#define CVUI_IMPLEMENTATION#include <cvui.h>extern "C"{#include <uv.h>}using namespace std;#define WINDOW_NAM......

IOTService
今天
1
0
openJDK之JDK9的String

1.openJDK8的String 先来看下openJDK8的String的底层,如下图1.1所示: 图1.1 底层上使用的是char[],即char数组 每个char占16个bit,Character.SIZE的值是16。 2.openJDK9中的String 图2.1...

克虏伯
今天
1
0
UEFI 模式下如何安装 Ubuntu 16.04

作者:知乎用户 链接:https://www.zhihu.com/question/52092661/answer/259583475 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 针对UEFI模式下安装U...

寻知者
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部