您的位置:首页 > 编程语言 > PHP开发

PHP获取IP所在地区

2013-07-01 11:22 225 查看

转载自http://www.phper.org.cn/?post=88

这是一个PHP获取客户端IP所在地区的类,它能根据IP地址查地区,简单实用。

使用示例

示例一:view sourceprint?

1.
$IpLocation

=
new
IpLocation();

2.
$client

=
$IpLocation
->getlocation();

3.
print_r(
$client
);


示例二:view sourceprint?

1.
$IpLocation

=
new
IpLocation(
'../qqwry/QQWry.Dat'
);

2.
$client

=
$IpLocation
->getlocation(
'115.148.101.72'
);

3.
print_r(
$client
);


相关说明

此类要求提供纯真IP数据库,附件包里包含有此数据库。

在线演示

IP地址查询在线演示:http://down.phper.org.cn/ip/

iplocation.class.php

view sourceprint?

001.
class

IpLocation

002.
{

003.
/**

004.
* QQWry.Dat文件指针

005.
* @var resource

006.
*/

007.
var

$fp
;

008.

009.
/**

010.
* 第一条IP记录的偏移地址

011.
* @var int

012.
*/

013.
var

$firstip
;

014.

015.
/**

016.
* 最后一条IP记录的偏移地址

017.
* @var int

018.
*/

019.
var

$lastip
;

020.

021.
/**

022.
* IP记录的总条数(不包含版本信息记录)

023.
* @var int

024.
*/

025.
var

$totalip
;

026.

027.
/**

028.
* 返回读取的长整型数

029.
* @access private

030.
* @return int

031.
*/

032.
function

getlong()

033.
{

034.
$result

=unpack(
'Vlong'
,
fread
(
$this
->fp,4));
//将读取的little-endian编码的4个字节转化为长整型数

035.
return

$result
[
'long'
];

036.
}

037.

038.
/**

039.
* 返回读取的3个字节的长整型数

040.
* @access private

041.
* @return int

042.
*/

043.
function

getlong3()

044.
{

045.
$result

=unpack(
'Vlong'
,
fread
(
$this
->fp,3).
chr
(0));
//将读取的little-endian编码的3个字节转化为长整型数

046.
return

$result
[
'long'
];

047.
}

048.

049.
/**

050.
* 返回压缩后可进行比较的IP地址

051.
* @access private

052.
* @param string $ip

053.
* @return string

054.
*/

055.
function

packip(
$ip
)

056.
{

057.
// 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False,

058.
// 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串

059.
return

pack(
'N'
,
intval
(
ip2long
(
$ip
)));
//intaval 获取变量的整数值

060.
}

061.

062.
/**

063.
* 返回读取的字符串

064.
* @access private

065.
* @param string $data

066.
* @return string

067.
*/

068.
function

getstring(
$data

=
""
)

069.
{

070.
$char

=
fread
(
$this
->fp,1);

071.
while

(ord(
$char
)> 0)
// 字符串按照C格式保存,以\0结束 ord()得到字符的ASCII码

072.
{

073.
$data

.=
$char
;
// 将读取的字符连接到给定字符串之后

074.
$char

=
fread
(
$this
->fp,1);

075.
}

076.
return

$data
;

077.
}

078.

079.
/**

080.
* 返回地区信息

081.
* @access private

082.
* @return string

083.
*/

084.
function

getarea()

085.
{

086.
$byte

=
fread
(
$this
->fp,1);
// 标志字节

087.
switch

(ord(
$byte
)){

088.
case

0:
// 没有区域信息

089.
$area

=
""
;

090.
break
;

091.
case

1:

092.
case

2:
// 标志字节为1或2,表示区域信息被重定向

093.
fseek
(
$this
->fp,
$this
->getlong3());

094.
$area

=
$this
->getstring();

095.
break
;

096.
default
:
// 否则,表示区域信息没有被重定向

097.
$area

=
$this
->getstring(
$byte
);

098.
break
;

099.
}

100.
return

$area
;

101.
}

102.

103.
/**

104.
* 根据所给 IP 地址或域名返回所在地区信息

105.
* @access public

106.
* @param string $ip

107.
* @return array

108.
*/

109.
function

getlocation(
$ip

=
''
)

110.
{

111.
if

(!
$this
->fp)
return
null;

// 如果数据文件没有被正确打开,则直接返回空

112.
if
(
$ip

==
''
)
$ip
=
$this
->clientIp();

113.
$location
[
'ip'
] =
gethostbyname
(
$ip
);
// 将输入的域名转化为IP地址

114.
$ip

=
$this
->packip(
$location
[
'ip'
]);
// 将输入的IP地址转化为可比较的IP地址

115.

116.
$l

=0;                                         
// 搜索的下边界

117.
$u

=
$this
->totalip;
// 搜索的上边界

118.
$findip

=
$this
->lastip;
// 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息)

119.
while

(
$l

<=
$u
) 

// 当上边界小于下边界时,查找失败

120.
{

121.
$i

=
floor
((
$l

+
$u
)/ 2);
// 计算近似中间记录

122.
fseek
(
$this
->fp,
$this
->firstip +

$i
* 7);

123.
$beginip

=
strrev
(
fread
(
$this
->fp,4));
// 获取中间记录的开始IP地址

124.

125.
if

(
$ip
<
$beginip
)
// 用户的IP小于中间记录的开始IP地址时

126.
{

127.
$u

=
$i
- 1;
// 将搜索的上边界修改为中间记录减一

128.
}

129.
else

130.
{

131.
fseek
(
$this
->fp,
$this
->getlong3());

132.
$endip

=
strrev
(
fread
(
$this
->fp,4));
// 获取中间记录的结束IP地址

133.
if

(
$ip
>
$endip
)

// 用户的IP大于中间记录的结束IP地址时

134.
{

135.
$l

=
$i

+1;
// 将搜索的下边界修改为中间记录加一

136.
}

137.
else

// 用户的IP在中间记录的IP范围内时

138.
{

139.
$findip

=
$this
->firstip +
$i
* 7;

140.
break
;
// 则表示找到结果,退出循环

141.
}

142.
}

143.
}

144.

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

146.
fseek
(
$this
->fp,
$findip
);

147.
$location
[
'beginip'
] =long2ip(
$this
->getlong());
// 用户IP所在范围的开始地址

148.
$offset

=
$this
->getlong3();

149.
fseek
(
$this
->fp,
$offset
);

150.
$location
[
'endip'
] =long2ip(
$this
->getlong());
// 用户IP所在范围的结束地址

151.
$byte

=
fread
(
$this
->fp,1);
// 标志字节

152.
switch

(ord(
$byte
))

153.
{

154.
case

1:
// 标志字节为1,表示国家和区域信息都被同时重定向

155.
$countryOffset

=
$this
->getlong3();
// 重定向地址

156.
fseek
(
$this
->fp,
$countryOffset
);

157.
$byte

=
fread
(
$this
->fp,1);
// 标志字节

158.
switch

(ord(
$byte
))

159.
{

160.
case

2:
// 标志字节为2,表示国家信息又被重定向

161.
fseek
(
$this
->fp,
$this
->getlong3());

162.
$location
[
'country'
] =
$this
->getstring();

163.
fseek
(
$this
->fp,
$countryOffset
+4);

164.
$location
[
'area'
] =
$this
->getarea();

165.
break
;

166.
default
:
// 否则,表示国家信息没有被重定向

167.
$location
[
'country'
] =
$this
->getstring(
$byte
);

168.
$location
[
'area'
] =
$this
->getarea();

169.
break
;

170.
}

171.
break
;

172.
case

2:
// 标志字节为2,表示国家信息被重定向

173.
fseek
(
$this
->fp,
$this
->getlong3());

174.
$location
[
'country'
] =
$this
->getstring();

175.
fseek
(
$this
->fp,
$offset
+8);

176.
$location
[
'area'
] =
$this
->getarea();

177.
break
;

178.
default
:
// 否则,表示国家信息没有被重定向

179.
$location
[
'country'
] =
$this
->getstring(
$byte
);

180.
$location
[
'area'
] =
$this
->getarea();

181.
break
;

182.
}

183.

184.
if

(
$location
[
'country'
] ==
" CZ88.NET"
)    

// CZ88.NET表示没有有效信息

185.
{

186.
$location
[
'country'
] =
"未知"
;

187.
}

188.
if

(
$location
[
'area'
] ==
" CZ88.NET"
)

189.
{

190.
$location
[
'area'
] =
""
;

191.
}

192.
return

$location
;

193.
}

194.

195.
/**

196.
* 获取客户端IP地址

197.
* */

198.
function

clientIp(){

199.
if
(
getenv
(
'HTTP_CLIENT_IP'
)&& 
strcasecmp
(
getenv
(
'HTTP_CLIENT_IP'
),
'unknown'
)){

200.
$onlineip

=
getenv
(
'HTTP_CLIENT_IP'
);

201.
}
elseif
(
getenv
(
'HTTP_X_FORWARDED_FOR'
)&&
strcasecmp
(
getenv
(
'HTTP_X_FORWARDED_FOR'
),
'unknown'
)){

202.
$onlineip

=
getenv
(
'HTTP_X_FORWARDED_FOR'
);

203.
}
elseif
(
getenv
(
'REMOTE_ADDR'
)&&
strcasecmp
(
getenv
(
'REMOTE_ADDR'
),
'unknown'
)){

204.
$onlineip

=
getenv
(
'REMOTE_ADDR'
);

205.
}
elseif
(isset(
$_SERVER
[
'REMOTE_ADDR'
])&&
$_SERVER
[
'REMOTE_ADDR'
] &&
strcasecmp
(
$_SERVER
[
'REMOTE_ADDR'
],
'unknown'
)){

206.
$onlineip

=
$_SERVER
[
'REMOTE_ADDR'
];

207.
}

208.
preg_match(
"/[\d\.]{7,15}/"
,
$onlineip
,
$onlineipmatches
);

209.
$onlineip

=
$onlineipmatches
[0] ?
$onlineipmatches
[0] :

'unknown'
;

210.
unset(
$onlineipmatches
);

211.
return

$onlineip
;

212.
}

213.

214.
/**

215.
* 构造函数,打开 QQWry.Dat 文件并初始化类中的信息

216.
* @param string $filename

217.
* @return IpLocation

218.
*/

219.
function

IpLocation(
$filename

=
""
)

220.
{

221.
if
(!
$filename
)
$filename
=dirname(
__FILE__
).
'/qqwry/QQWry.Dat'
;

222.
if
(!
file_exists
(
$filename
))
exit
(
'qqwry.dat is not exists!'
);

223.
if

((
$this
->fp =@
fopen
(
$filename
,
'rb'
))!==false)

224.
{

225.
$this
->firstip =
$this
->getlong();

226.
$this
->lastip =
$this
->getlong();

227.
$this
->totalip =(
$this
->lastip
-
$this
->firstip)/ 7;

228.
register_shutdown_function(
array
(&
$this
,
'_IpLocation'
));

229.
}

230.
}

231.

232.
/**

233.
* 析构函数,用于在页面执行结束后自动关闭打开的文件。

234.
*/

235.
function

_IpLocation()

236.
{

237.
fclose(
$this
->fp);

238.
}

239.
}


附件下载:

iplocation.class.rar 2.93MB

« 最近写的一个JS排版工具|
JS判断浏览器版本号»

相关文章:

.htaccess的基本作用及相关语法介绍

PHP邮件接收类的改进

PHP生成二维码图像的类QRcode

网站重新开通,欢迎大家光临。

PHP在线手册

post by
PHPER | 2010-10-18 20:38 Monday | 文章 |

引用地址:

评论

凯凯 2012-06-05 08:58
嗯,不错,很ok,谢谢楼主咯~~~

Gavin 2011-09-16 11:48
哈哈

Gavin 2011-09-16 11:44
可以,值得收藏,博主转载你的,没关系吧

流水 2011-04-05 17:34
嗯嗯,正在写一个小程序,要用到IP地址和地理位置,谢谢博主!

闲逛
2010-12-28 19:02
有些地址返回的是国家,有些是国家的省份城市,不知道有没有单纯的返回国家代码的IP数据库

杨银川 2010-11-23 11:45
我用 php调用的时候出现乱码

如何解决?

Array ( [ip] => 115.148.101.72 [beginip] => 115.148.68.0 [endip] => 115.148.127.255 [country] => ??ηʡ?Ӗ݊Њ [area] => ?琅 )博主回复:需要注意编码,如果你用的是utf8编码的话需要进行转换,具体是从gbk到utf8,编码转换可以参考:http://www.phper.org.cn/?post=54
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: