`
sofire
  • 浏览: 145384 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

QQWry.datIP地址库的查询程序

阅读更多
改写了QQIP地址库的查询程序,学习了怎么操作文件。
也学会了正确使用tar命令。
本来想把 ip.d ip.php 和 QQWry.dat 文件打包成 a.tgz的,
结果把命令写成了 tar czf ip.d ip.php QQWry.dat a.tgz
把辛辛苦苦的写的程序给覆盖了:(
重新写了一遍,发现还是很快的。

/**
 * QQWry.dat IP地址库的查找程序
 * Edit by Liu Dehong @ 2007/08/08
 * Version: 1.0.0
 *
 * 改编自 马秉尧 的PHP程序
 * QQWry.dat 来自于 CZ88.net
 * Q数据库的格式参考:http://www.pconline.com.cn/pcedu/empolder/gj/java/0505/612860.html
 */

import std.stdio;
import std.stream;
import std.string;
import std.math;

extern(C)
{
    uint ntohl(uint);
    uint inet_addr(char *cp);
    uint  htonl(uint hostlong);
    char* inet_ntoa(in_addr);
    struct in_addr
    {
        uint s_addr;
    }
}

uint ip2long(char[] ip)
{
    return ntohl(inet_addr(toStringz(ip)));
}

char[] long2ip(ulong ip)
{
    in_addr myaddr;
	myaddr.s_addr = htonl(ip);
	return toString(inet_ntoa(myaddr)).dup;
}

class IpLocation
{
    private File m_file;
    private uint m_firstip;          // 第一条IP记录的偏移地址
    private uint m_lastip;           // 最后一条IP记录的偏移地址
    private uint m_totalip;          // IP记录的总条数(不包含版本信息记录)

    static assert (int.sizeof == 4);
    static assert (uint.sizeof == 4);
    static assert (long.sizeof == 8);

    /* 从文件读取4个字节,返回整型数
     */
    uint get4Byte() 
    {
        uint i;
        m_file.read(i);
        return i;
    }
    
    /* 从文件读取3个字节的数据,返回整型数
     */
    uint get3Byte() 
    {
        ubyte c;
        uint sum;
        int[3] pow = [1, 256, 256*256];
        /**
         * 如读取的是 2 34 56 ,则结果是 2 + 34*256 + 56*256*256
         */
        for (int i; i < 3; i++)
        {
            m_file.read(c);
            sum += c * pow[i];
        }
        return sum;
    }
    
    /* 返回读取的字符串
     */
    char[] getString() 
    {
        debug(1) writefln("GetString's pos: %d(%X)", m_file.position, m_file.position);

        ubyte c;
        char[] str = new char[100]; // guess
        int i;
        for (i = 0; true; i++)
        {
            m_file.read(c);
            if (c == 0)                     // 字符串按照C格式保存,以\0结束
                break;
            if (i == str.length)
                str.length = str.length * 2;
            str[i] = c;
        }
        str.length = i;
        return str;
    }

    /* 返回地区信息
     */
    char[] getArea() 
    {
        debug(1) writefln("GetArea's pos: %d(%X)", m_file.position, m_file.position);

        ubyte flag;                         // 标志字节
        char[] area;

        m_file.read(flag);
        switch (flag) 
        {
        case 0:      
            // 没有区域信息
            area = "";
            break;

        case 1:
        case 2:                             
            // 标志字节为1或2,表示区域信息被重定向
            m_file.position(get3Byte());
            area = getString();
            break;

        default: 
            // 否则,表示区域信息没有被重定向
            area = cast(char)flag ~ getString();      // flag 是一个字符
            break;
        }
        return area;
    }
    
    /* 根据所给 IP 地址或域名返回所在地区信息
     * 索取区按照地址从小到大排列,用折半算法查找
     */
    string[string] getLocation(char[] addr) 
    {
        if ( ! m_file.readable) 
            return null;

        /* 查找纪录区的位置
         */
        uint l = 0;                         // 搜索的下边界
        uint u = m_totalip;                 // 搜索的上边界
        uint findip = m_lastip;             // 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息)
        uint i;

        uint beginip;
        uint endip;

        auto ip_t = ip2long(addr);

        while (l <= u)                      // 当上边界小于下边界时,查找失败
        {                  
            i = std.math.lround((l + u) / 2);  
            m_file.position(m_firstip + i * 7);
            m_file.read(beginip);
            if (ip_t < beginip) 
            {
                u = i - 1; 
            }
            else 
            {
                m_file.position(get3Byte());
                m_file.read(endip);
                if (ip_t > endip) 
                {
                    l = i + 1;
                }
                else 
                {
                    findip = m_firstip + i * 7;  // find it
                    break;
                }
            }
        }
    
        debug(1) writefln("Findip is: %d(%#X)", findip, findip);

        /* 获取查找到的IP地理位置信息
         */

        string[string] location;
        m_file.position(findip);
        location["beginip"] = long2ip(get4Byte());          // 用户IP所在范围的开始地址

        auto offset = get3Byte();
        m_file.position(offset);
        location["endip"] = long2ip(get4Byte());            // 用户IP所在范围的结束地址
        
        ubyte flag1, flag2;                 // 标志字节
        m_file.read(flag1);    
        switch (flag1) 
        {
        case 1:
            // 标志字节为1,表示国家和区域信息都被同时重定向
            auto countryOffset = get3Byte();                // 重定向地址
            m_file.position(countryOffset);
            m_file.read(flag2);    // 标志字节
            switch (flag2) 
            {
            case 2:
                // 标志字节为2,表示国家信息又被重定向
                m_file.position(get3Byte());
                location["country"] = getString();
                m_file.position(countryOffset + 4);
                location["area"] = getArea();
                break;

            default:
                // 否则,表示国家信息没有被重定向
                location["country"] = cast(char)flag2 ~ getString();  // flag2 是一个字符
                location["area"] = getArea();
                break;
            }
            break;

        case 2:
            // 标志字节为2,表示国家信息被重定向
            m_file.position(get3Byte());
            location["country"] = getString();
            m_file.position(offset + 8);                    // IP地址(4B) + 定向模式(1B) + 偏移地址(3B)
            location["area"] = getArea();
            break;

        default:
            // 否则,表示国家信息没有被重定向
            location["country"] = cast(char)flag1 ~ getString();      // flag1是一个字符
            location["area"] = getArea();
            break;
        }

        debug(1) writefln("Flag1&2 : %d %d", flag1, flag2);

        if (location["country"] == " CZ88.NET")             // CZ88.NET表示没有有效信息
        {
            location["country"] = "unkown";
        }
        if (location["area"] == " CZ88.NET") 
        {
            location["area"] = "";
        }
        return location;
    }
    
    /**
     * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息
     */
    this(char[] filename = "QQWry.Dat") 
    {
        m_file      = new File(filename);
        m_firstip   = get4Byte();
        m_lastip    = get4Byte();
        m_totalip   = (m_lastip - m_firstip) / 7;
    }

    uint firstip()
    {
        return m_firstip;
    }
    uint lastip()
    {
        return m_lastip;
    }
    uint totalip()
    {
        return m_totalip;
    }
}

void main()
{

    auto ipObj = new IpLocation;

    writefln("First IP is: %s", ipObj.firstip);
    writefln("Last IP is : %s", ipObj.lastip);
    writefln("Total ip is: %s", ipObj.totalip);
    
    string[] myips = [
        "0.255.255.255",
        "0.255.255.255",
        "1.255.255.255",
        "4.10.255.255",
        "4.10.255.255",
        "4.19.77.255",
        "59.57.7.206",
        "222.79.141.30",
        "211.100.32.245",
        "202.106.184.145",
        "202.205.82.122",
        "0.1.163.136",
    ];

    string[string] loc;
    foreach (int k, string v; myips)
    {
        loc = ipObj.getLocation(v);
        printf("%*s in [%.*s ~ %.*s]"\n, v, loc["beginip"], loc["endip"]);
        printf("Country: %-20.*s Area: %-20.*s"\n, loc["country"], loc["area"]);
    }
}
  • IpLocation.zip (3.2 MB)
  • 描述: 包括:D语言的源程序,PHP版本的程序,QQWry的数据库文件和格式说明文件
  • 下载次数: 44
分享到:
评论

相关推荐

    QQWry.DatIP数据库导入SQL,IPData 2011最新版IP库

    QQWry.DatIP数据库是网络上广泛使用的IP地址数据库,它包含了全球众多IP地址的地理定位信息。这个数据库主要用于帮助系统快速识别和定位互联网用户的地理位置。2011年发布的IPData 2011最新版IP库,是当时最新的IP...

    java实现qqWry.datIP查询源码

    QQWry.dat是一个IP地址数据库,用于快速查询IP地址对应的地理位置信息。下面将详细阐述这些知识点。 1. **Java编程语言**: Java是一种广泛使用的面向对象的编程语言,具有跨平台性、安全性、稳定性和高性能等特点...

    qqwry.datIP地址信息

    // QQWry.Dat文件指针 var $fp; var $firstip; var $lastip; var $totalip; function getlong() { //unpack从二进制字符串对数据进行解包 //将读取的little-endian编码的4个字节转化为长整型数,fread安全...

    qqwry.dat纯真ip数据库和自动更新脚本

    qqwry.dat qqwry 纯真IP数据库文件,dat数据非exe安装包,每天会扫描两次(17:55和23:55),当发现更新时也可以选择手动运行...2、qqwry.py 文件用于获取“纯真IP实验室”最新微信公众号推文内发布的免费IP库的下载链接

    qqwry.dat, 纯真IP地址数据库镜像,mirror of qqwry.dat.zip

    qqwry.dat, 纯真IP地址数据库镜像,mirror of qqwry.dat.zip

    通过qqwry.dat解析IP地址的动态库源代码

    确保程序有读取qqwry.dat的权限,并检查代码是否与Windows 7系统兼容。 总结,通过解析qqwry.dat数据库,我们可以快速地获取到任意IP地址的地理位置信息。这个过程涉及到二进制文件操作、数据结构设计、搜索算法...

    PHP调用QQWry.Dat 实现IP归属地查询

    QQWry.Dat是由网络服务商提供的一种IP地址库,包含了大量IP地址与对应地理位置的映射关系,更新频繁,可以满足实时查询的需求。 首先,我们需要了解PHP的基本语法和文件操作。PHP是一种服务器端脚本语言,广泛应用...

    QQWry.dat.zip

    QQWry.dat是一个知名的IP地址库,用于快速查询和定位全球IP地址的地理位置信息。这个压缩包文件"QQWry.dat.zip"包含了QQWry.dat这个数据库文件,它被广泛应用于各种软件和网络服务中,以帮助用户识别和追踪互联网上...

    qqwry.dat 纯真20230920最新稳定版

    qqwry.dat纯真IP 2023年9月更新 2023年最新版 相对于上个版本最新更新超过了100000个IP信息

    GeoIP.dat,qqhostinfo.pm、qqwry.pl、QQWry.dat3 打包下载

    qqwry.pl可以集成到其他应用程序中,用于快速查询IP地址的相关信息,帮助分析和处理网络数据。 4. **QQWry.dat3**:这是QingWry数据库的一个版本,包含了最新的IP地址和地理位置信息。与GeoIP.dat类似,它用于快速...

    PHP 根据IP地址获取所在城市代码以及纯真ip库qqwry.dat下载

    纯真IP库(qqwry.dat)是中国流行的IP地址数据库,包含了大量的IP段和对应的地理位置信息。这个数据库文件以特定的格式存储数据,便于快速查找。使用这种库可以高效地将IP地址映射到城市或其他地理位置,避免了每次...

    IP定位QQwry.dat文件

    QQwry.dat文件是与IP定位相关的数据文件,主要用于快速查询和识别IP地址对应的地理位置信息。这个文件在技术社区中被广泛分享,因为其便捷性和实用性。本文将深入探讨QQwry.dat的背景、工作原理以及如何利用它进行IP...

    qqwry.dat 纯真ip数据库

    qqwry.dat 纯真ip数据库 附在线升级工具 下载下来直接安装即可,ip数据库(qqwry.dat)在安装所在目录下

    qqwry.zip 2019年IP地址库 7月更新qqwry.dat 纯真IP库 dat文件 QQ IP数据库 纯真版 20190705

    qqwry.dat 20190705更新的地址库 全球地址库 很全很新,纯真IP库 QQ IP数据库 纯真版收集了包括中国电信、中国移动、中国联通、长城宽带、聚友宽带等 ISP 的最新准确 IP 地址数据。包括 最全的网吧数据。希望能够通过...

    qqwry.dat纯真ip库,根据IP获取地区运营商,2019-9-12上传,精准无误

    qqwry.bat,纯真ip库,根据IP获取地区运营商,2019-9-12上传,精准无误

    QQWry.Dat ip 库

    QQWry.Dat ip库 收集了包括中国电信、中国网通、长城宽带、网通宽带、聚友宽带等 ISP 的最新准确 IP 地址数据。包括 最全的网吧数据。

    如何借助qqwry.dat文件实现查询指定IP所属地的共能

    本文将详细介绍如何利用qqwry.dat文件来查询指定IP地址的归属地。qqwry.dat是由腾讯公司维护的一个IP数据库,它包含了全球范围内的IP地址与对应地理位置的映射关系,更新频繁,准确性较高。 首先,了解qqwry.dat...

Global site tag (gtag.js) - Google Analytics