QQ IP 地址查询相关
1.QQwry.dat格式分析和查询IP位置的PHP程序
以前的追捕数据库太大,而且很久没有更新了。
所以我想到利用QQwry.dat这个文件查询IP所在位置,QQwry.dat 在很多地方都能找到,一般看IP地址的QQ压缩包中都有。
但是没有任何相关格式资料。
我分析了这个文件的格式,目前如下结论:
格式如下:
A。文件头,共8字节
B。若干条记录的结束地址+国家和区域
C。按照从小到大排列的若干条起始地址+结束地址偏移,定长,7字节
D。所有的IP都是用4字节整数记录的,并且遵照Intel次序,高位在后,低位在前。
E。所有偏移量都是绝对偏移,就是从文件最开头计算。
F。除了文件头用了两个4字节偏移,其余偏移量都用3字节。
G。所有的偏移量也是低位在前,高位在后
H。采用了一些字符串压缩技术
1。文件头,共8字节
FirstStartIpOffset:4 第一个起始IP的绝对偏移
LastStartIpOffset:4 最后一个起始IP的绝对偏移
2。起始地址+结束地址偏移记录区
每条记录7字节,按照起始地址从小到大排列
StartIp:4 起始地址,整数形式的IP
EndIpOffset:3 结束地址绝对偏移
3。结束地址+国家+区域记录区
EndIP:4
国家+区域记录:不定长
4。国家+区域记录,有几种形式
4.1。
国家字符串,以 0×0 结束
区域字符串,以 0×0 结束
4.2。
Flag:1 标识取值: 0×1,后面没有Local记录
0×2,后面还有Local记录
sCountryOffset:3 实际的字符串要去这个偏移位置去找
LocalRec:不定长,可选 根据Flag取值而定。这个记录也类似Country,可能采用压缩
4.3 LocalRec结构一
flag:1 还不是十分了解这个flag含义,取值 0×1 or 0×2
sLocalOffset:3
4.4 LocalRec结构二
sLocal:不定长 普通的C风格字符串
注意:sCountryOffset指向的位置可能依然是4.2格式的,不知道为什么这样设计。
Flag取0×1时,sCountryOffset指向的位置可能是Flag为0×2,这时,LocalRec也在这里寻找。
现在不明白当记录Local的位置遇到0×2的标志意味着什么。
在qqwry.dat中,似乎存在一些错误。
个别的记录Local会被写为:
0×2,0×0,0×0,0×0
根据规则,应该到文件最开头去寻找,可是,文件最开头显然不是记录这些的。
我才学PHP不久,各位不要笑,你要能改进当然好,记得给我一份。
我参考了一些网上找到的代码,就不一一写出出处了。
说老实话,我很头疼PHP无法明确指定变量的类型。
比如,我想让某个数是无符号的整形,它很不听话,非要是带个负号,我只好尝试各种可能的写法……….
各位都是怎么处理类似的事情?
define(‘QQWRY’ , $qqwry_root_path . ‘QQwry.dat’ ) ;
function IpToInt($Ip) {
$array=explode(‘.’,$Ip);
$Int=($array[0] * 256*256*256) + ($array[1]*256*256) + ($array[2]*256) + $array[3];
return $Int;
}
function IntToIp($Int) {
$b1=($Int & 0xff000000)>>24;
if ($b1<0) $b1+=0×100;
$b2=($Int & 0x00ff0000)>>16;
if ($b2<0) $b2+=0×100;
$b3=($Int & 0x0000ff00)>>8;
if ($b3<0) $b3+=0×100;
$b4= $Int & 0x000000ff;
if ($b4<0) $b4+=0×100;
$Ip=$b1.’.’.$b2.’.’.$b3.’.’.$b4;
return $Ip;
}
class TQQwry
{
var $StartIP = 0;
var $EndIP = 0;
var $Country = ”;
var $Local = ”;
var $CountryFlag = 0; // 标识 Country位置
// 0×01,随后3字节为Country偏移,没有Local
// 0×02,随后3字节为Country偏移,接着是Local
// 其他,Country,Local,Local有类似的压缩。可能多重引用。
var $fp;
var $FirstStartIp = 0;
var $LastStartIp = 0;
var $EndIpOff = 0 ;
function getStartIp ( $RecNo ) {
$offset = $this->FirstStartIp + $RecNo * 7 ;
@fseek ( $this->fp , $offset , SEEK_SET ) ;
$buf = fread ( $this->fp , 7 ) ;
$this->EndIpOff = ord($buf[4]) + (ord($buf[5])*256) + (ord($buf[6])* 256*256);
$this->StartIp = ord($buf[0]) + (ord($buf[1])*256) + (ord($buf[2])*256*256) + (ord($buf[3])*256*256*256);
return $this->StartIp ;
}
function getEndIp ( ) {
@fseek ( $this->fp , $this->EndIpOff , SEEK_SET ) ;
$buf = fread ( $this->fp , 5 ) ;
$this->EndIp = ord($buf[0]) + (ord($buf[1])*256) + (ord($buf[2])*256*256) + (ord($buf[3])*256*256*256);
$this->CountryFlag = ord ( $buf[4] ) ;
return $this->EndIp ;
}
function getCountry ( ) {
switch ( $this->CountryFlag ) {
case 1:
case 2:
$this->Country = $this->getFlagStr ( $this->EndIpOff+4) ;
//echo sprintf(‘EndIpOffset=(%x)’,$this->EndIpOff );
$this->Local = ( 1 == $this->CountryFlag )? ” : $this->getFlagStr ( $this->EndIpOff+8);
break ;
default :
$this->Country = $this->getFlagStr ($this->EndIpOff+4) ;
$this->Local = $this->getFlagStr ( ftell ( $this->fp )) ;
}
}
function getFlagStr ( $offset )
{
$flag = 0 ;
while ( 1 ){
@fseek ( $this->fp , $offset , SEEK_SET ) ;
$flag = ord ( fgetc ( $this->fp ) ) ;
if ( $flag == 1 || $flag == 2 ) {
$buf = fread ($this->fp , 3 ) ;
if ($flag == 2 ){
$this->CountryFlag = 2 ;
$this->EndIpOff = $offset – 4 ;
}
$offset = ord($buf[0]) + (ord($buf[1])*256) + (ord($buf[2])* 256*256);
}else{
break ;
}
}
if ( $offset < 12 )
return ”;
@fseek($this->fp , $offset , SEEK_SET ) ;
return $this->getStr();
}
function getStr ( )
{
$str = ” ;
while ( 1 ) {
$c = fgetc ( $this->fp ) ;
if ( ord ( $c[0] ) == 0 )
break ;
$str .= $c ;
}
return $str ;
}
function qqwry ($dotip) {
$nRet;
$ip = IpToInt ( $dotip );
$this->fp= @fopen(QQWRY, "rb");
if ($this->fp == NULL) {
$szLocal= "OpenFileError";
return 1;
}
@fseek ( $this->fp , 0 , SEEK_SET ) ;
$buf = fread ( $this->fp , 8 ) ;
$this->FirstStartIp = ord($buf[0]) + (ord($buf[1])*256) + (ord($buf[2])*256*256) + (ord($buf[3])*256*256*256);
$this->LastStartIp = ord($buf[4]) + (ord($buf[5])*256) + (ord($buf[6])*256*256) + (ord($buf[7])*256*256*256);
$RecordCount= floor( ( $this->LastStartIp – $this->FirstStartIp ) / 7);
if ($RecordCount <= 1){
$this->Country = "FileDataError";
fclose ( $this->fp ) ;
return 2 ;
}
$RangB= 0;
$RangE= $RecordCount;
// Match …
while ($RangB < $RangE-1)
{
$RecNo= floor(($RangB + $RangE) / 2);
$this->getStartIp ( $RecNo ) ;
if ( $ip == $this->StartIp )
{
$RangB = $RecNo ;
break ;
}
if ( $ip > $this->StartIp)
$RangB= $RecNo;
else
$RangE= $RecNo;
}
$this->getStartIp ( $RangB ) ;
$this->getEndIp ( ) ;
if ( ( $this->StartIp <= $ip ) && ( $this->EndIp >= $ip ) ){
$nRet = 0 ;
$this->getCountry ( ) ;
//这样不太好…………..所以……….
$this->Local = str_replace("(我们一定要解放台湾!!!)", "", $this->Local);
}else {
$nRet = 3 ;
$this->Country = ‘未知’ ;
$this->Local = ” ;
}
fclose ( $this->fp ) ;
return $nRet ;
}
}
function ip2location ( $ip )
{
$wry = new TQQwry ;
$nRet = $wry->qqwry ( $ip );
//可以利用 $nRet做一些事情,我是让他自动记录未知IP到一个表,代码就不写了。
return $wry->Country.$wry->Local ;
}
突然在某某网站看到IP地址查询,于是心血来潮做了一个。这是用asp查询全球IP地址的程式,由于类似的的用Asp查询IP的速度不是很理想,本人使用的也是宏志宏的IP地址数据库,只是对它进行了改进。
本人在 win98+pws+access2000上测试通过,效果比较理想。
数据库的设计在一个软件中的比例,毫不夸张的说占60%,虽然这是一个小的程式,但也得到一定的体现。
有任何错误或建议请一定要给我发E-mail: ljz811@163.com ,我也不了解“追捕”等类似算法,欢迎交流,谢谢!
好了废话少说,开始吧。
1、 转wry.dll为.mdb由于我们要优化数据库(适合我们用的),建议这样做:
将文件改为wry.xls用Excel打开。
在Access中新建表IP
字段名 类型 长度 说明
————————————————————————————————————
id 自动编号
newid 数字 5 startip前三个数字
seconded 数字 5 startip第二部分三个数字
startip 文本 20 起始IP段
endip 文本 20 止 IP 段
country 文本 此段IP所在国家或省
local 文本 此段IP所在地
从Excel中copy startip/endip/country/local 四个字段至Access ,id会自动添加,对于newid和secondid当然我们不可能手工添加,可以这样实现。
<!–#include file="dbpath.asp"–>
<%
sqlcmd="select * from ip"
‘建议使用sqlcmd="select * from ipwhere id>=值1 and id<值2" ,因为对于一万个左右的数据一下子添加资源占用很大
set rs=ip.execute(sqlcmd)
do while not rs.eof
fir=left(rs("startip"),3)
sec=mid(rs("startip"),5,3)
sqlcmd3="update ip set newid=’"&str&"’,secondid=’"sec"’ "
ip.execute sqlcmd3
rs.movenext
loop
%>
这样就完成数据库的修改,对于dbpath.asp 文件下面讲
2、 文件介绍
本程序分 dbpath.asp 和 search.asp
以下是源程序及简要描述
Dbpath.Asp 代码如下:(本人命名数据库名字为ip.mdb)
<%@ Language=VBScript %>
<% set ip=server.createobject("ADODB.CONNECTION")
ip.Open "driver={Microsoft Access Driver (*.mdb)};dbq=" & Server.MapPath("ip.mdb") %>
search.asp 代码如下:
<!–#include file="dbpath.asp"–>
<%
‘ Write by 尥蹶子
‘ If you find some error or you have better idea
‘ Please contact me
‘ My Email: ljz811@163.com Oicq:30763914
%>
<%
‘建立一个提交的表单
%>
<BODY bgColor=azure>
<P align=center>IP查询<BR><BR><BR>
<FORM action="index.asp" method=post id=form1 name=form1>
<font size=2>输入IP:</font><INPUT id=text1 name=putip
style ="BACKGROUND-COLOR: lavender; HEIGHT: 22px; WIDTH: 182px" >
<INPUT id=submit1 name=sub1 style="BACKGROUND-COLOR: lightblue; FONT-SIZE: 12" type=submit value="我查" tabindex="0">
</FORM>
<%
userip=Request.ServerVariables ("REMOTE_ADDR")
listip=trim(request("putip"))
if listip="" or listip=" " then
Response.Write "<p align=center><font size=2>请输入IP地址!</font></p>"
else
‘—判断访问者的IP是否与输入的ip同
cmp=strcomp(userip,listip,1)
if cmp=0 then %>
<p align=center><font size=2 >这就是你自己呀!</p>
<%
else
‘获得输入ip的第1段,并置3位
num1=Instr(listip,".")
‘判断第一段是否正确
if mun1=1 then
Response.Write "<p align=center>"&listip&"<br>"&" <font size=2 >非有效的IP地址,IP每段必须1~3位!</p>"
else
fir=left(listip,num1-1)
if len(fir)=2 then
fir=0&fir
end if
if len(fir)=1 then
fir=0&fir
fir=0&fir
end if
‘获得输入ip的第2段,并置3位
num2=Instr(num1+1,listip,".")
sec=mid(listip,num1+1,num2-(num1+1))
if len(sec)=2 then
sec=0&sec
end if
if len(sec)=1 then
sec=0&sec
sec=0&sec
end if
‘获得输入ip的第3段,并置3位
num3=Instr(num2+1,listip,".")
thr=mid(listip,num2+1,num3-(num2+1))
if len(thr)=2 then
thr=0&thr
end if
if len(thr)=1 then
thr=0&thr
thr=0&thr
end if
‘获得输入ip的第4段,并置3位
fou=right(listip,len(listip)-num3)
if len(fou)=2 then
fou=0&fou
end if
if len(fou)=1 then
fou=0&fou
fou=0&fou
end if
‘判断是否为有效IP
if len(fir)=0 or len(fir)>3 or len(sec)=0 or len(sec)>3 or len(thr)=0 or len(thr)>3 or len(fou)=0 or len(fou)>3 then
Response.Write "<p align=center>"&listip&"<br>"&" <font size=2 >非有效的IP地址,IP每段必须1~3位!</p>"
else
‘判断是否为保留地址
if ((fir>=0) and (fir<= 2)) or ((fir>=58) and (fir<=60)) or ((fir>=67) and (fir<=126)) then
Response.Write "<p align=center>"&listip&"<br>"&" <font size=2 >Internet IP保留地址!</p>"
else
‘判断是否为分配地址
if (fir>=219 and fir<=223) or fir=225 then
Response.Write "<p align=center>"&listip&"<br>"&" <font size=2 >此IP地址尚未分配!</p>"
else
if fir>255 or fir<0 or sec>255 or sec<0 or thr>255 or thr<0 or fou>255 or fou<0 then
Response.Write "<p align=center>"&listip&"<br>"&" <font size=2 >Internet IP地址输入值不正确!</p>"
else
‘查询IP地址数据库
Set sql= Server.CreateObject("ADODB.Recordset")
rs1="select id,startip,endip,country,local from ip where id<9904 and newid="&fir&" and secondid="&sec&" "
sql.open rs1,ip,1,1
‘对于类似224.000.000.000~224.255.255.255的ip地址进行处理
if sql.RecordCount = 1 then
sql.Close
sqlcmd2="select id,startip,endip,country,local from ip where id<9904 and newid="&fir&" and secondid="&sec&" order by id desc"
set rs=ip.execute(sqlcmd2)
else
sqlcmd2="select id,startip,endip,country,local from ip where id<9904 and newid="&fir&" order by id desc"
set rs=ip.execute(sqlcmd2)
if rs.eof then
%>
<br><br><font size="2"><P align=center><%=listip%><br>★未知IP数据★<BR>如果你知道请告诉我! OICQ:30763914 谢谢!<BR>=尥蹶子=</font></P>
<% else
do while not rs.eof
‘******* 处理country or local为空的情况,使用了按id倒排(why?因为根据IP地址表可知,先列大地区的ip段,例如先列出欧洲的 062.000.000.000~062.255.255.255,再列英国等IP段)
‘对后面三段IP进行处理,是否在IP表内
if (sec>=(mid(rs("startip"),5,3)) and (sec<=mid(rs("endip"),5,3))) and (thr>=(mid(rs("startip"),9,3)) and (thr<=mid(rs("endip"),9,3))) and (fou>=(mid(rs("startip"),13,3)) and (fou<=mid(rs("endip"),13,3))) then
%>
<center><font size=2><%=listip%><br><%=rs("country")%> <%=rs("local")%></font></center>
<%
‘若查到数据,马上跳出以免占用资源
exit do
else
end if
if rs.eof then
‘如果没有打出提示
%>
<br><br><font size="2"><P align=center><%=listip%><br>★未知IP数据★<BR>如果你知道请告诉我! OICQ:30763914 谢谢!<BR>=尥蹶子=</font></P>
<%
end if
rs.movenext
loop
end if
end if
%>
<%
end if
end if%>
<%end if%>
<%end if%>
<%end if%>
<%end if%><%end if%>
</BODY>
</HTML>
<?php
/**********************************************************************
* IP 来源追踪 Ver 1.1a
* 作者 耙子 pazee@21cn.com http://www.fogsun.com
* 2002/08/10
*
* 程序中的数据库来自《追捕》,请把追捕中wry.dll 拷贝到函数当前目录。
* 追捕的数据库是个的dbf文件,只不过它的扩展名字变成了dll。
* 2000年我在一个偶然的机会发现了他的dll的真实格式,后来的很多文章也提到了此格式,
* 《追捕》的数据文件目前应用非常广泛,很多查IP来源程序的基本都用到了他的数据库。
* 比如有个去广告,能显示IP来源的QQ就使用了他。
* 2001年初写过一个php的函数,但是需要php的dbf模块支持,很多网站并不提供此模块。
* 现在的版本采用二进制的文件读写,不依赖php的dbf的支持了,没有用到
* 任何shell命令.
* 由于数据文件本身是有序的,所以非常方便的采用了折半查找的算法,
* 速度很快,目前的20020325版本的数据库,大约有记录28905条,最多比较14次。
*
* 在此感谢《追捕》作者“冯志宏”
* 有任何问题请于我联系,谢谢! pazee@21cn.com
*
*
* 声明:
* 你可以随意传播、复制、修改此程序,但是请保留此段文字。
* 代码请勿用在商业软件上、请勿用在不正当的地方(这是《追捕》的要求),
* 再次表示谢谢。
***********************************************************************/
// define path of wry.dll
define("DBFILENAME", "wry.dll");
class TRec
{
var $StartIP;
var $EndIP;
var $Country;
var $Local;
}
class TWru
{
var $ip;
var $fp;
var $Rec;
var $DATAFIELDBEGIN= 0xc2;
var $RECORDLENGTH;
// Check IP and Format IP
function FormatIP($ip)
{
$ret= ereg("^([0-9]+).([0-9]+).([0-9]+).([0-9]+)$", $ip, $IPSection);
if ($ret == false)
return -1; // Invild IP
$this->ip= ””;
for ($i=1; $i<=4; $i++)
if ($IPSection[$i] > 255)
return -1;
else
$this->ip.= sprintf("%03.0f", $IPSection[$i]). (($i<4) ? ”.” : ””);
return 0;
}
// read a record from DB
function ReadRec($RecNo)
{
$this->Seek($RecNo);
$buf= fread($this->fp, $this->RECORDLENGTH);
if (strlen($buf) == 0)
{
return 1;
}
$this->Rec->StartIP= (substr($buf, 0, 17));
$this->Rec->EndIP= trim(substr($buf, 17, 22));
$this->Rec->Country= trim(substr($buf, 17+22, 13));
$this->Rec->Local= trim(substr($buf, 17+22+13, 47));
return 0;
}
// Go to Record Number
function Seek($RecNo)
{
return fseek($this->fp, $RecNo * $this->RECORDLENGTH + $this->DATAFIELDBEGIN, SEEK_SET);
}
// Where_are_you Main Fucntion
/*********************************************
* 使用说明
* 参数:
* IP 合法IP地址即可
* szLocal 是保存返回的结果字符串的
* 返回值:
* 此函数有返回值,可以根据返回值自行处理结果
* 0: 查找成功
* -1: 无效的IP
* 1: 打开数据库文件失败
* 2: 数据文件错误(没找到有效记录)
* 3: 未知 IP
**********************************************/
function wru($ip, &$szLocal)
{
$this->Rec= new TRec;
$nRet= 0;
$this->RECORDLENGTH= 17 + 22 + 13 + 47 + 12 + 1;
if ($this->FormatIP($ip) != 0)
{
$szLocal= "InvalidIP";
return -1;
}
$this->fp= fopen(DBFILENAME, "rb");
if ($this->fp == NULL) {
$szLocal= "OpenFileError";
return 1;
}
// Get Record Count
fseek($this->fp, 0, SEEK_END);
$RecordCount= floor((ftell($this->fp) – $this->DATAFIELDBEGIN) / $this->RECORDLENGTH);
if ($RecordCount <= 1)
{
$szLocal= "FileDataError";
$nRet= 2;
}
else
{
$RangB= 0;
$RangE= $RecordCount;
// Match …
while ($RangB < $RangE-1)
{
$RecNo= floor(($RangB + $RangE) / 2);
$this->ReadRec($RecNo);
if (strcmp($this->ip, $this->Rec->StartIP) >=0 && strcmp($this->ip, $this->Rec->EndIP) <=0 )
break; //Found match record
if (strcmp($this->ip, $this->Rec->StartIP) > 0)
$RangB= $RecNo;
else
$RangE= $RecNo;
}
if (!($RangB < $RangE-1))
{
$szLocal= "UnknowLocal!";
$nRet= 3;
}
else
{ // Match Success
$szLocal= $this->Rec->Country;
$szLocal.= $this->Rec->Local;
}
}
fclose($this->fp);
return $nRet;
}
}
/*******************************************************************
* 变更记录:
* 2002/08/10 完成版本 1.0a
* 2002/08/12 增加FormatIP成员函数,提供了对IP的标准格式化,支持
* 202.96.128.68 这类的写法,类的内部自动转为 202.096.128.068,
* 同时提供了完整的对IP地址的有效检查。规则是4个整数部分均不超
* 过255的自然数。
* ********************************************************************/
?>
<?
// Test Code.
$wru= new TWru;
$szResult="";
$ip= "202.96.134.133";
// $ip= $REMOTE_ADDR;
$wru->wru($ip, $szResult);
echo $ip."<br>";
echo $szResult;
//—————————————————————————
?>
QQWry.dll 是cnss设计的格式
采用的是索引+二分查找来减小内存占用和提高查找速度.
由于采用二分查找,所以IP数据要被分为最小的片,假设有A,B两条数据,B数据完全覆盖A数据,那么转换为QQwry 后两条数据就变成了三条.如果原始数据非常有条理,就可以避免这个现象,不过这是不可能的,几万条数据会越来越乱,所以QQwry的尺寸会迅速增加,之所以增长的不是特别快,是因为格式对重复数据有一定压缩.
QQwry.dat:"咦?我没吃那么多,怎么胖的那么快!?"
那篇文章是作者猜测的格式,我再把原来整理的发一遍吧.0×2 0×0 0×0 0×0不是错误,可能是给御风而行放版权信息的地方,另外附带ipsearcher.dll源码.
———————————————–
新格式说明
主要分为数据区和索引区
★数据区元素:
存放IP信息中的:结束IP(4字节),国家(不定长),地区(不定长)
排列顺序:无要求
★索引区元素:
存放IP信息中的:起始IP(4字节),索引值(3字节)
排列顺序:起始IP按升序排列
★IP为4字节,如"255.0.0.0"表示为0xFF000000,存在文件中则为00 00 00 FF(字节序原因)
★索引值为该IP消息的<结束IP、国家、地区>在文件中的位置。指向<结束IP>
★如果结束IP后的字节为0×01,则说明该IP消息的<国家、地区>与前面的IP信息重复,这时0×01后面的3个字节为国家、地区字符串的偏移量。可以根据这三个字节去前面找国家、地区。
★如果国家的第一个字节为0×02,说明该国家串与前面的国家或地区串重复,0×02后面的三个字节为该串的偏移量,可以根据该偏移量找到前面的串。
★如果地区的第一个字节为0×02,说明该地区串与前面的国家或地区串重复,0×02后面的三个字节为该串的偏移量,可以根据该偏移量找到前面的串。
★有可能在出现0×01的情况下出现0×02,这时需要跳转两次查找国家、地区字符串。
★正常的字符串以NULL做结尾。
★IP信息不允许有重复、覆盖
★使用索引是为了保证能以线性速度搜索
★新格式不允许为未知数据的IP消息,原格式中的未知数据已经都去掉了。如果有未知数据的IP信息,将大大增加文件长度。
文件的头4个字节是索引区第一个元素的偏移量,第二个4字节是索引区最后一个元素的偏移量。通过这两个偏移量,可以用二分法快速查找IP信息。如:一条IP信息是,要查询的IP为150
起始 结束 国家 地区
100 200 中国 北京
首先在索引区找到起始IP小于150的最后一个元素,通过索引,找到结束IP,如果150大于结束IP,说明是未知数据;如果150小于等于结束IP,则找到国家、地区。
ipsearch.dll
// ipsearcher.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
extern "C" __declspec(dllexport) void* __cdecl _GetAddress(const char *IPstr);
void *ret[2]; //for return
char *ptr = NULL; //ptr of image
char *p = NULL; //point to index
unsigned int total; //ip count
inline unsigned int get_3b(const char *mem)
{
return 0x00ffffff & *(unsigned int*)(mem);
}
inline void Load(void)
{
HANDLE hnd; //file handle
DWORD NumberOfBytesRead; //len
char text[2048]; //patch
char *temp;
unsigned int len;
//get patch
if( !GetModuleFileName(0, text, 2048) )
return;
temp = strrchr(text, 92); // 92 = ”
*(temp + 1) = NULL;
strcat(temp, "QQwry.dat");
//CreateFile
hnd = CreateFile(text, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hnd)
{
::MessageBox(NULL, text, "不能打开文件!", NULL);
return;
}
//get len
len = SetFilePointer(hnd, NULL, NULL, FILE_END);
SetFilePointer(hnd, NULL, NULL, FILE_BEGIN);
//malloc
ptr = (char*)malloc(len+9);
if(!ptr)
{
CloseHandle(hnd);
::MessageBox(NULL, "不能分配内存!", NULL, NULL);
return;
}
//read
if(!ReadFile(hnd, ptr, len, &NumberOfBytesRead, NULL))
{
CloseHandle(hnd);
free(ptr);
::MessageBox(NULL, text, "不能读入文件!", NULL);
return;
}
CloseHandle(hnd);
//calc total – 1
total = (*((unsigned int*)ptr+1) – *(unsigned int*)ptr);
//check file
if(total % 7 != 0)
{
free(ptr);
::MessageBox(NULL, text, "QQwry.dat文件有损坏!", NULL);
return;
}
total /= 7;
++total;
p = ptr + *(unsigned int*)ptr; //ptr of index area
}
inline unsigned int str2ip(const char *lp)
{
unsigned int ret = 0;
unsigned int now = 0;
while(*lp)
{
if(‘.’ == *lp)
{
ret = 256 * ret + now;
now = 0;
}
else
now = 10 * now + *lp – ’0′;
++lp;
}
ret = 256 * ret + now;
return ret;
}
void* __cdecl _GetAddress(const char *IPstr)
{
if(NULL == p)
{
ret[0] = "无法打开数据";
ret[1] = "";
return ret;
}
unsigned int ip = str2ip(IPstr);
char *now_p;
unsigned int begin = 0, end = total;
while(1)
{
if( begin >= end – 1 )
break;
if( ip < *(unsigned int*)(p + (begin + end)/2 * 7) )
end = (begin + end)/2;
else
begin = (begin + end)/2;
}
unsigned int temp = get_3b(p + 7 * begin + 4);
if(ip <= *(unsigned int*)(ptr + temp)) //ok, found
{
now_p = ptr + temp + 4;
if( 0×01 == *now_p )
now_p = ptr + get_3b(now_p + 1);
//country
if( 0×02 == *now_p ) //jump
{
ret[0] = ptr + get_3b(now_p + 1);
now_p += 4;
}
else
{
ret[0] = now_p;
for(; *now_p; ++now_p)
;
++now_p;
}
//local
if( 0×02 == *now_p ) //jump
ret[1] = ptr + get_3b(now_p + 1);
else
ret[1] = now_p;
}
else
{
ret[0] = "未知数据";
ret[1] = "";
}
return ret;
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch(ul_reason_for_call)
{
//case DLL_THREAD_ATTACH:
//case DLL_THREAD_DETACH:
case DLL_PROCESS_ATTACH: //attach
{
Load();
}
break;
//————————————
case DLL_PROCESS_DETACH: //detach
{
free(ptr);
}
}
return true;
}
<?php
$ip = $REMOTE_ADDR; // Get visitor’s ip address
$connection = mysql_connect("your host", "your login", "your password") or die ("ERROR");
$db= mysql_select_db(your_db,$connection) or die ("ERROR");
$fact = explode(".",$ip); // create an array with the ip numbers
$ip_code = $fact[3] + $fact[2]*256 + $fact[1] * 65536 + $fact[0] * 16777216; // calculate the base 10 ip
// now I execute a query to select a ip range that fits with my visitor’s ip
$sql = "select * from world_ip where $ip_code <= real_end_ip and $pi_code >= real_start_ip";
$result = mysql_query($sql,$connection) or die ("ERROR in $sql");
$row = mysql_fetch_array($result);
echo $row[long_nation];
?>
QQ IP 地址查询相关的更多相关文章
- IP地址查询接口
新浪的IP地址查询接口:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js 新浪多地域测试方法:http://int.dpool. ...
- 齐全的IP地址查询接口及调用方法(转)
设计蜂巢IP地址查询接口:http://www.hujuntao.com/api/ip/ip.php 腾讯IP地址查询接口:http://fw.qq.com/ipaddress 新浪IP地址查询接口: ...
- API之IP地址查询---权威的IP地址查询接口集合
原文地址:http://yushine.iteye.com/blog/1717586 推荐实用IP138 http://www.baidu.com/s?wd=IP&rsv_spt=1& ...
- 微信小程序开发-IP地址查询-例子
微信小程序开发 小程序搜索框 IP地址查询 搜索查询 样例 微信小程序 开发 参考 https://mp.weixin.qq.com/debug/wxadoc/dev/component/ ...
- IP地址查询接口及调用方法
1.查询地址 搜狐IP地址查询接口(IP):http://pv.sohu.com/cityjson 1616 IP地址查询接口(IP+地址):http://w.1616.net/chaxun/ipto ...
- [1]IP地址查询
今天起开始玩百度APIStore里面的免费API.以前用过的有12306的:数据.接口,有时间整理出来,12306的有点乱就是了.还有扇贝以及有道的API,之前用在留言板里自动翻译,公司用过百度地图以 ...
- 根据IP地址查询所在地
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Tex ...
- Android中由IP地址查询经纬度坐标的实例
大家都知道,根据IP地址就可以知道它所在的具体位置,在Android中同样可以由IP地址得到它的位置,即具体的地理经纬度坐标. 本文就直接以代码的方式演示如何根据IP地址查询地理经纬度坐标位置,下面的 ...
- python requests库爬取网页小实例:ip地址查询
ip地址查询的全代码: 智力使用ip183网站进行ip地址归属地的查询,我们在查询的过程是通过构造url进行查询的,将要查询的ip地址以参数的形式添加在ip183url后面即可. #ip地址查询的全代 ...
随机推荐
- React Native 性能优化指南【全网最全,值得收藏】
2020 年谈 React Native,在日新月异的前端圈,可能算比较另类了.文章动笔之前我也犹豫过,但是想到写技术文章又不是赶时髦,啥新潮写啥,所以还是动笔写了这篇 React Native 性能 ...
- list查询
public List<MISSINGISTEMS> getMissList(MISSINGISTEMS missingistems) throws Exception { List< ...
- 浏览器从输入url 到页面展示完成响应过程
用户从输入 url 到浏览器响应,呈现给用户的具体过程 1.用户在输入栏输入地址 (1) 如果有 beforeunload 事件会先执行判断继续还是跳出操作 (2) 浏览器进程识别是 地址还是关键字检 ...
- java 字典 map 和 list.forEach
1.keySet key 集 2.values value 集(为何不叫valueSet)... 3.entrySet key value 集 List<?> 循环 1.Iterable ...
- 重拾c++第二天(4):复合类型
1.定义:种类 数组名[元素个数] = {元素1,...,元素n} ,或者直接赋值:数组名[元素位置] = 值; 2.部分初始化,其他全为0,可以就定义一个0,这样得到0数组(或者就一个{},别的啥也 ...
- transient简介
当一个对象实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的 ...
- 多级反向代理java获取真实IP地址
public static String getIpAddress(HttpServletRequest request){ String ip = request.getHeader("x ...
- Git The requested URL returned error:403
一.问题描述 hexo部署的仓库需要换到另一个账号上,于是按照之前创建的步骤,修改了hexo安装目录下的deploy的repo地址,然而hexo s和hexo g没出错,但是hexo d时,会出错. ...
- SEO 搜索 形成一个关联
- Java程序员学习Go指南(二)
摘抄:https://www.luozhiyun.com/archives/211 Go中的结构体 构建结构体 如下: type AnimalCategory struct { kingdom str ...