- 浏览: 1523093 次
- 性别:
- 来自: 厦门
文章分类
- 全部博客 (516)
- Java (49)
- Java/Struts 2.0 (25)
- Java/Spring、Spring MVC (11)
- Java/Quartz (3)
- Java/Lucene (6)
- Java/Hibernate (19)
- Java/openJPA (7)
- Java/DWR (7)
- Java/Security、Spring Security/OAuth2 (6)
- Java/Threading (9)
- Java/XML (22)
- java/design pattern (4)
- Android (2)
- JavaScript (46)
- jquery (3)
- DB/MySQL (23)
- DB/Oracle (16)
- PHP (25)
- CSS (20)
- Linux (38)
- C/C++、DLL、Makefile、VC++ (31)
- 正则 (9)
- Eclipse (4)
- 安全、网络等概念 (25)
- 集群 (7)
- 网页 (5)
- 视频\音频 (1)
- HTML (6)
- 计算机数学/算法 (3)
- Virtualbox (1)
- LDAP (2)
- 数据挖掘 (6)
- 工具破解 (1)
- 其他 (13)
- Mail (1)
- 药材 (3)
- 游戏 (2)
- hadoop (13)
- 压力测试 (3)
- 设计模式 (3)
- java/Swing (2)
- 缓存/Memcache (0)
- 缓存/Redis (1)
- OSGI (2)
- OSGI/Gemini (0)
- 文档写作 (0)
- java/Servlet (3)
- MQ/RabbitMQ (2)
- MQ/RocketMQ (0)
- MQ/Kafka (1)
- maven (0)
- SYS/linux (1)
- cache/redis (1)
- DB/Mongodb (2)
- nginx (1)
- postman (1)
- 操作系统/ubuntu (1)
- golang (1)
- dubbo (1)
- 技术管理岗位 (0)
- mybatis-plus (0)
最新评论
-
pgx89112:
大神,请赐我一份这个示例的项目代码吧,万分感谢,1530259 ...
spring的rabbitmq配置 -
string2020:
不使用增强器 怎么弄?
OpenJPA的增强器 -
孟江波:
学习了,楼主,能否提供一份源代码啊,学习一下,十分感谢!!!4 ...
spring的rabbitmq配置 -
eachgray:
...
spring-data-redis配置事务 -
qljoeli:
学习了,楼主,能否提供一份源代码啊,学习一下,十分感谢!!!1 ...
spring的rabbitmq配置
http://blog.csdn.net/clin003/archive/2007/08/14/1743157.aspx
利用 QQWry.Dat 实现 IP 地址高效检索(PHP)
根据 LumaQQ 开发者文档中的纯真 IP 数据库格式详解,我编写了一个 PHP 的查询
IP 所在地区信息的类。在编写过程中发现纯真 IP 数据库格式详解中关于记录区的描述不是很全面,不过出入也不是很大,所以我没必要再写一份纯真 IP
数据库的格式说明了,大家感兴趣的话,读一读下面的代码应该就能看出来了。代码中加了很详细的注释,应该很容易读懂的。
在创建这个类的一个实例后,实例中就保存了打开的文件指针和一些查询需要的信息,每次查询时不需要重新打开文件,直到页面执行结束后,打开的文件才会自动关闭。这样。在一个页面内进行多次查询时,效率是很高的。并且此类不仅可以直接查询
IP,还可以自动将域名解析为 IP 进行查询。
下面是程序代码:
<?php /** * IP 地理位置查询类 * * @author 马秉尧 * @version 1.5 * @copyright 2005 CoolCode.CN */ class IpLocation { /** * QQWry.Dat文件指针 * * @var resource */ var $fp; /** * 第一条IP记录的偏移地址 * * @var int */ var $firstip; /** * 最后一条IP记录的偏移地址 * * @var int */ var $lastip; /** * IP记录的总条数(不包含版本信息记录) * * @var int */ var $totalip; /** * 返回读取的长整型数 * * @access private * @return int */ function getlong() { //将读取的little-endian编码的4个字节转化为长整型数 $result = unpack('Vlong', fread($this->fp, 4)); return $result['long']; } /** * 返回读取的3个字节的长整型数 * * @access private * @return int */ function getlong3() { //将读取的little-endian编码的3个字节转化为长整型数 $result = unpack('Vlong', fread($this->fp, 3).chr(0)); return $result['long']; } /** * 返回压缩后可进行比较的IP地址 * * @access private * @param string $ip * @return string */ function packip($ip) { // 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False, // 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串 return pack('N', intval(ip2long($ip))); } /** * 返回读取的字符串 * * @access private * @param string $data * @return string */ function getstring($data = "") { $char = fread($this->fp, 1); while (ord($char) > 0) { // 字符串按照C格式保存,以�结束 $data .= $char; // 将读取的字符连接到给定字符串之后 $char = fread($this->fp, 1); } return $data; } /** * 返回地区信息 * * @access private * @return string */ function getarea() { $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 0: // 没有区域信息 $area = ""; break; case 1: case 2: // 标志字节为1或2,表示区域信息被重定向 fseek($this->fp, $this->getlong3()); $area = $this->getstring(); break; default: // 否则,表示区域信息没有被重定向 $area = $this->getstring($byte); break; } return $area; } /** * 根据所给 IP 地址或域名返回所在地区信息 * * @access public * @param string $ip * @return array */ function getlocation($ip) { if (!$this->fp) return null; // 如果数据文件没有被正确打开,则直接返回空 $location['ip'] = gethostbyname($ip); // 将输入的域名转化为IP地址 $ip = $this->packip($location['ip']); // 将输入的IP地址转化为可比较的IP地址 // 不合法的IP地址会被转化为255.255.255.255 // 对分搜索 $l = 0; // 搜索的下边界 $u = $this->totalip; // 搜索的上边界 $findip = $this->lastip; // 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息) while ($l <= $u) { // 当上边界小于下边界时,查找失败 $i = floor(($l + $u) / 2); // 计算近似中间记录 fseek($this->fp, $this->firstip + $i * 7); $beginip = strrev(fread($this->fp, 4)); // 获取中间记录的开始IP地址 // strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式 // 以便用于比较,后面相同。 if ($ip < $beginip) { // 用户的IP小于中间记录的开始IP地址时 $u = $i - 1; // 将搜索的上边界修改为中间记录减一 } else { fseek($this->fp, $this->getlong3()); $endip = strrev(fread($this->fp, 4)); // 获取中间记录的结束IP地址 if ($ip > $endip) { // 用户的IP大于中间记录的结束IP地址时 $l = $i + 1; // 将搜索的下边界修改为中间记录加一 } else { // 用户的IP在中间记录的IP范围内时 $findip = $this->firstip + $i * 7; break; // 则表示找到结果,退出循环 } } } //获取查找到的IP地理位置信息 fseek($this->fp, $findip); $location['beginip'] = long2ip($this->getlong()); // 用户IP所在范围的开始地址 $offset = $this->getlong3(); fseek($this->fp, $offset); $location['endip'] = long2ip($this->getlong()); // 用户IP所在范围的结束地址 $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 1: // 标志字节为1,表示国家和区域信息都被同时重定向 $countryOffset = $this->getlong3(); // 重定向地址 fseek($this->fp, $countryOffset); $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 2: // 标志字节为2,表示国家信息又被重定向 fseek($this->fp, $this->getlong3()); $location['country'] = $this->getstring(); fseek($this->fp, $countryOffset + 4); $location['area'] = $this->getarea(); break; default: // 否则,表示国家信息没有被重定向 $location['country'] = $this->getstring($byte); $location['area'] = $this->getarea(); break; } break; case 2: // 标志字节为2,表示国家信息被重定向 fseek($this->fp, $this->getlong3()); $location['country'] = $this->getstring(); fseek($this->fp, $offset + 8); $location['area'] = $this->getarea(); break; default: // 否则,表示国家信息没有被重定向 $location['country'] = $this->getstring($byte); $location['area'] = $this->getarea(); break; } if ($location['country'] == " CZ88.NET") { // CZ88.NET表示没有有效信息 $location['country'] = "未知"; } if ($location['area'] == " CZ88.NET") { $location['area'] = ""; } return $location; } /** * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息 * * @param string $filename * @return IpLocation */ function IpLocation($filename = "QQWry.Dat") { $this->fp = 0; if (($this->fp = @fopen($filename, 'rb')) !== false) { $this->firstip = $this->getlong(); $this->lastip = $this->getlong(); $this->totalip = ($this->lastip - $this->firstip) / 7; //注册析构函数,使其在程序执行结束时执行 register_shutdown_function(array(&$this, '_IpLocation')); } } /** * 析构函数,用于在页面执行结束后自动关闭打开的文件。 * */ function _IpLocation() { if ($this->fp) { fclose($this->fp); } $this->fp = 0; } } ?>
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)
发表评论
-
mysql_query()防止掉链的数据库查询
2011-03-24 14:00 1730// ---------------------------- ... -
Windows下的Memcache安装
2011-03-22 10:06 2108转自:http://www.ccvita.com/258.ht ... -
PHP 解决采集乱码问题mb_convert_encoding和iconv使用比较
2011-02-11 13:27 3002转自:http://hi.baidu.com/ ... -
采集数据
2011-01-28 17:27 923<? // 连接数据库的配置 $config = a ... -
eclipse xdebug 配置手册
2010-10-22 14:12 1249XDebug Support In PDT 1.0 :htt ... -
file_get_contents的超时处理
2010-08-17 14:57 2145转自:http://www.neatstudio.com/sh ... -
在php 5.2版本之前使用的json_encode和json_decode函数
2010-08-13 09:33 1832http://mike.teczno.com/JSON/JSO ... -
月份处理函数
2010-08-11 22:00 1014function period_diff($in_dateLo ... -
配置xdebug
2010-08-10 09:19 971zend_extension = "D:/xampp ... -
判断在linux以命令行执行的文件是否还在执行
2010-06-03 10:37 2136// 取得当前程序进程,用来判断是否可以执行 $gather ... -
PHP分页
2010-05-05 07:15 1128<?php header("content- ... -
JavaBridge
2010-02-10 16:11 865中文翻译及使用手册 http://programfan.co ... -
How to implement COMET with PHP
2009-12-07 13:17 3021http://www.zeitoun.net/articles ... -
PHP 压缩网站上的文件,并返回下载
2009-08-27 20:51 2710<?php $zipFileName = " ... -
递归删除目录及目录中的文件
2009-08-27 20:24 1230<?php /** * 递归删除目录及目录中的文件 ... -
PHP验证码程序:session生成图片
2009-08-07 15:39 3881昨天捣鼓了一下PHP验证码并生成图片程序,采用了sessi ... -
Apache的rewrite规则详细介绍
2009-06-01 22:52 1356rewrite标志 R [=code](for ... -
php mail 支持UTF-8,附件
2009-03-06 14:19 2889<?php class mime_mail { var ... -
php 多语言切换
2009-02-27 09:55 10171目录结构: //================= ... -
包含其他目录的文件
2009-02-02 16:57 989<?php include_once dirname(_ ...
相关推荐
这可以通过二分查找算法(Binary Search)来实现,因为QQWry.Dat文件中的IP地址通常是按照升序排列的。二分查找可以显著提高查询效率,尤其在处理大量数据时。 ```php function binarySearch($data, $ip) { $low =...
qqwry.dat是由QQ公司提供的一种IP地址数据库,包含了全球大部分IP地址与其对应国家、地区的映射关系。这个数据库文件小巧高效,是快速查找IP地址地理信息的常用工具。其工作原理是通过二进制格式存储IP段和地理位置...
qqwry.dat qqwry 纯真IP数据库文件,dat数据非exe安装包,每天会扫描两次(17:55和23:55),当发现更新时也可以选择手动运行来获得文件。 目录说明 1、qqwry.dat 为最新数据直链(即下即用),每次更新会覆盖之前的...
本项目基于Java编程语言,利用QQWry.Dat数据库文件实现了IP到地理位置的映射,使得开发者可以轻松地在自己的应用中集成这一功能。QQWry.Dat是一个包含全球IP地址和对应地理位置信息的数据库,它被广泛用于快速查询IP...
qqwry.dat, 纯真IP地址数据库镜像,mirror of qqwry.dat.zip
qqwry.dat 纯真ip数据库 附在线升级工具 下载下来直接安装即可,ip数据库(qqwry.dat)在安装所在目录下
qqwry.dat纯真IP 2023年9月更新 2023年最新版 相对于上个版本最新更新超过了100000个IP信息
纯真IP库(qqwry.dat)是中国流行的IP地址数据库,包含了大量的IP段和对应的地理位置信息。这个数据库文件以特定的格式存储数据,便于快速查找。使用这种库可以高效地将IP地址映射到城市或其他地理位置,避免了每次...
4. **QQWry.dat3**:这是QingWry数据库的一个版本,包含了最新的IP地址和地理位置信息。与GeoIP.dat类似,它用于快速查找IP地址对应的地理位置,但可能更侧重于中国及亚洲地区的IP数据,提供更精确的国内地区信息。 ...
QQWry.dat是一个知名的IP地址库,用于快速查询和定位全球IP地址的地理位置信息。这个压缩包文件"QQWry.dat.zip"包含了QQWry.dat这个数据库文件,它被广泛应用于各种软件和网络服务中,以帮助用户识别和追踪互联网上...
在Java编程中,读取纯真IP数据库QQwry.dat是为了实现快速地查询IP地址对应的城市和地区信息。QQwry.dat是一种广泛使用的IP地址库,它包含了大量的IP地址及其地理位置信息,通常用于网络日志分析、网站访问统计、地理...
总结,通过QQwry.dat获取IP地址所在地是一种常见且实用的方法,尤其在处理大量IP查询时,由于其高效的二进制查找机制,能显著提升性能。理解QQwry.dat的结构和查询流程,对于开发相关功能或者优化现有服务具有重要的...
QQwry.dat文件是与IP定位相关的数据文件,主要用于快速查询和识别IP地址对应的地理位置信息。这个文件在技术社区中被广泛分享,因为其便捷性和实用性。本文将深入探讨QQwry.dat的背景、工作原理以及如何利用它进行IP...
Java读取qqwry.dat实现IP地域查询是网络编程中的一种常见需求,特别是在开发服务器端应用、游戏插件或者网络安全工具时。qqwry.dat是一个包含全球IP地址及其对应地理位置信息的数据文件,由著名的IP查询库——...
在实现.NET QQwry.dat IP地址设计的经典代码时,开发者可能会利用这些工具读取文件,逐个处理条目,并建立一个高效的查询结构,比如平衡二叉搜索树(AVL树)或者B树,以便于快速查找特定IP对应的国家/地区信息。...
qqwry.dat 20190705更新的地址库 全球地址库 很全很新,纯真IP库 QQ IP数据库 纯真版收集了包括中国电信、中国移动、中国联通、长城宽带、聚友宽带等 ISP 的最新准确 IP 地址数据。包括 最全的网吧数据。希望能够通过...
QQWry.dat是由“纯真IP数据库”提供的IP地址解析文件,主要用于将IPv4地址转换为地理位置信息。这个数据库由热心网友维护,定期更新,包含了大量全球IP地址的对应信息,尤其是中国地区的IP数据。由于其准确性和实用...
QQWry.Dat是一个常用的IP地址数据库,它主要用于将IP地址转换为对应的地理位置信息,比如国家、地区等。这个数据库通常被各种网络应用和软件用来显示访客的来源地,或者进行网络管理与分析。在提供的压缩包中,...
4. 定位IP地址的算法会遍历QQWRY.DAT文件,通过二分查找或其他高效的搜索策略来快速定位到指定IP地址所在的记录,然后返回对应的国家和地区信息。 5. 源码还会包含异常处理机制,以应对如文件不存在、读取错误或IP...
在IT领域,有时候我们...总之,借助qqwry.dat文件查询IP地址所属地是一种高效且实用的方法,但要正确实现这一功能,必须熟悉二进制文件操作、编码转换以及搜索算法。对于开发人员来说,这是一个提高技术能力的好实践。