php读取qqwry.dat ip地址数据库文件程序

首先看看QQWry.Data文件的内容结构 ,以及解读方式 。

一、文件结构
文件主要分三个结构
1、文件头,8个字节;
2、数据记录区,不定长度;
3、索引区,长度为 7 的整数倍;

二、文件头
文件头的8个字节分两部分,每个部分4个字节,分别指定了索引区的开始地址和结束地址。所以可以通过两个地址的差值 除 7 后 加 1 可以计算出总的记录数。

二、记录区
记录区的数据需要通过索引区的数据来获得各个数据的起始位置;本区数据记录了IP地址的结束地址和地区字符串;所有地区字符串都以 0×00 为结束。

三、索引区
检索IP对应的地区,关键就是找到IP起始地址对应的索引内容。一个IP索引数据包含7个字节,前4个字节是IP地址起始值,后3个字节是对应的IP数据 记录在文件内的偏移地址;IP数据记录中,前 4 个字节是IP结束地址;紧跟的数据有两种模式: 0×01 模式 和 0×02 模式。

0×01模式,即在IP数据的第5个字节是 0×01,则在后面的 3 个字节是国家地区数据的偏移地址;国家地区数据包括国家和地区这两个字符串。即
—————————————————————
4字节 | 3字节 重定向 0x NN NN NN -> 国家地区数据的文件偏移地址
—————————————————————

0×02模式,即在IP数据的第5个字节是 0×02,则在后面的 3 个字节是国家数据的偏移地址,地区数据是再往后的字符串,以 0×00 截至。即
—————————————————————————–
4字节 | 3字节 重定向 0x NN NN NN -> 国家数据的文件偏移地址 | 地区字符串 | 0×00
—————————————————————————–

对于 0×01 模式所得到的 国家地区数据中,它可能又带有一个重定向结构,即
————————————–
国家字符串 | 0×00 | 地区字符串 | 0×00
————————————–

————————————————————————-
国家字符串 | 0×00 | 0×02 | 3字节 0x NN NN NN -> 地区字符串的文件偏移地址
————————————————————————-

对于前一种情况,比较简单,直接读出两个字符串数据就可以了;对于后一种情况,需要再次重定向到地区字符串的偏移地址,然后读取到 0×00 为字符串结尾。

对于这种采取地址映射实际字符串值的方式,主要作用是避免重复记录字符串值。在整个IP地址库文件中,有太多相同字符串记录了,采用 3 字节的映射地址要比重复记录字符串值节省太多空间了。

PHP代码读取操作QQWry.dat文件 :

 代码如下 复制代码

function bin2ip($bin){
 $ip = '';
 $bd = str_split($bin, 1);
 for($i = 4; $i > 0; $i--){
  $ip .= "." . sprintf("%03d", implode('', unpack('s', $bd[$i-1] . chr(0))));
 }
 return substr($ip, 1);
}

//--------------------------------------------------
$f = fopen('QQWry.Dat', 'r');
$c = fread($f, 4);
$d = fread($f, 4);

$index_begin = implode('', unpack('L', $c));
$index_end  = implode('', unpack('L', $d));
if($index_begin < 0) $index_begin += pow(2, 32);
if($index_end < 0) $index_end += pow(2, 32);

$ip_num = ($index_end - $index_begin) / 7 + 1;

echo "index begin at: $index_beginn";
echo "index end at: $index_endn";
echo "ip data count : $ip_numn";

$output = '';

for($i = 0; $i < $ip_num; $i++){

 //文件指针指到每个IP数据文件的索引取得索引数据(7字节)上
 fseek($f, $i * 7 + $index_begin);
 $ip4 = fread($f, 4); //IP起始地址
 if(strlen($ip4) < 4) exit('data file error');

 $ip3 = fread($f, 3); //IP记录偏移地址
 if(strlen($ip3) < 3) exit('data file error');

 $dataseek = implode('', unpack('L', $ip3 . chr(0)));
 if($dataseek < 0) $index_ip_record += pow(2, 32);

 //指向记录区 $dataseek 位置查找记录
 fseek($f, $dataseek);
 $ipdata = fread($f, 4); //IP结束地址
 if(strlen($ipdata) < 4) exit('data file error');

 $area = '';
 $country = '';

 //读一个标记位
 $flag = fread($f, 1);
 if($flag == chr(1)){ //国家名偏移标记位 模式一 0x01
  $area1seek = fread($f, 3);
  if(strlen($area1seek) < 3) exit('data file error');
  $area1seek = implode('', unpack('L', $area1seek . chr(0)));
  fseek($f, $area1seek);
  $flag = fread($f, 1); //可能又是标记位
 }
 if($flag == chr(2)){ //国家地区 重定向
  $area1seek = fread($f, 3);
  if(strlen($area1seek) < 3) exit('data file error');
  $area1seek = implode('', unpack('L', $area1seek . chr(0)));
  $flag = fread($f, 1);
  if($flag == chr(2)){
   $area2seek = fread($f, 3);
   $area2seek = implode('', unpack('L', $area2seek . chr(0)));
   fseek($f, $area2seek);
  }else{
   fseek($f, -1, SEEK_CUR);
  }
  while(($c = fread($f, 1)) != chr(0)) $area .= $c;
  fseek($f, $area1seek);
  while(($c = fread($f, 1)) != chr(0)) $country .= $c;
 }else{
  fseek($f, -1, SEEK_CUR);
  while(($c = fread($f, 1)) != chr(0)) $country .= $c;

  $flag = fread($f, 1); //如果地区是重定向的
  if($flag == chr(2)){
   $area2seek = fread($f, 3);
   $area2seek = implode('', unpack('L', $area2seek . chr(0)));
   fseek($f, $area2seek);
  }else{
   fseek($f, -1, SEEK_CUR);
  }
  while(($c = fread($f, 1)) != chr(0)) $area .= $c;
 }
 $adata = trim($country) . trim($area); //$country是国家字符串 , $area 是地区字符串
}
fclose($f);

这个函数我们看到最多的就是文件操作相关函数如fopen,fseek,fread这些,有需要的朋友可以看看。

时间: 2024-09-15 00:20:54

php读取qqwry.dat ip地址数据库文件程序的相关文章

php读取qqwry.dat ip地址定位文件的类实例代码

实例如下: <?php // +---------------------------------------------------------------------- // | // +---------------------------------------------------------------------- // | // +---------------------------------------------------------------------- cla

ASP 获取腾讯IP地址的接口程序代码

<script type=text/javascript教程 src=http://fw.qq.com/ipaddress></script> <script type=text/javascript> var hehe1=IPData[2] var hehe2=IPData[3] alert(hehe1); alert(hehe2); document.write(IPData.join(' ')); </script> 如何用ASP来存储,从上面读取出来

我如何用C#编写查看IP地址 的应用程序

问题描述 我如何用C#编写查看IP地址的应用程序 解决方案 解决方案二:System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName())解决方案三:谢谢大哥的指教,是不是这样呀?usingSystem;usingSystem.Net;usingSystem.IO;usingSystem.Data;usingSystem.Net.Dns;usingSystem.Text;namespaceCwpSoft.NetIP{publicclassN

导出QQWry.Dat中IP地址到文件[C#]

ip地址 下载CS文件:http://www.cnblogs.com/Files/rexsp/IPExport.rar /**//****************************************************************** ** File Name:IPExport.cs ** Copyright (c) 2004-2005 PPTech Studio(PPTech.Net) ** Creater:Rexsp(MSN:yubo@x263.net) ** C

c#如何能读取外网IP地址

问题描述 用c#编写程序如何能读取出用户是使用的路由器我要得到的是外网IP地址和他在内网的IP地址和计算机名称!列入用户使用路由器!客户登陆了我的网站这时候我就要得到他的外网IP地址和内网的IP地址和计算机名称!网站是要用C#写的B/S程序希望能讲详细点!我是刚学b/s的!谢谢大家我全部的家当都贡献出来了

asp.nep设计IP地址访问限制程序

ip添加页是用了一个ListBox, TextBox,两个Button 而在其他的页上则直接用当前IP对比数据库中的IP,代码如下! 限制IP添加页HTML代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ip.aspx.cs" Inherits="admin_ip" %> <!DOCTYPE html PUBLIC "-//W3C

如何编写显示IP地址的C#程序

问题描述 usingSystem;usingSystem.Net;usingSystem.IO;usingSystem.Data;usingSystem.Text;namespaceCwpSoft.NetIP{publicclassNetIP{staticvoidMain(){Console.WriteLine("您的IP地址是:{0}",System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName()));}}} 解决方案 解决

php获取ip地址所在地查询程序

 代码如下 复制代码 <?php header("content-Type: text/html; charset=utf-8");$weburl=$_SERVER['SERVER_NAME'];$weblink="http://".$weburl."/";if(count($_GET)>0){$urlip=array_keys($_GET);$urlip=str_replace("_","."

php 伪造ip地址来源实现程序

HTTP-REFERER这个变量已经越来越不可靠了,完全就是可以伪造出来的东东. 1.php 请求 2.php . 1.php代码:  代码如下 复制代码 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://localhost/2.php"); curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:8.8.8.8', 'CLIENT-IP:8.8.8.8'))