PHP转换IP地址到真实地址的方法详解
1. 利用纯真IP数据库
利用本地的QQWry.Dat文件,优点是查询速度非常快,缺点是数据库文件要放在自己的空间内并且要偶尔更新数据库。时间关系废话不多说,下面是 使用这个文件的函数,如果是在WordPress里面使用这个功能,把下面的代码写入主题下面的functions.php里面,然后在 comments-list的输出<?php echo convertip(get_comment_author_ip()); ?>即可;如果是其他程序引用,输入一个有效的IPv4地址就可以得到一个真实的地址。
//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';
}
$ipaddr = iconv('gbk', 'utf-8//IGNORE', $ipaddr); //转换编码,如果网页的gbk可以删除此行
return $ipaddr;
}
2. 利用门户网站的接口
目前已知的有腾讯、新浪、网易、搜狐和Google提供IP地址查询API,但是找得到的只有腾讯、新浪和网易的,Google的貌似要用 Google Maps所以没有研究。看了下国内的几个腾讯提供的是JavaScript的,网易提供的是XML,而新浪的有多种格式可以用,注意非XML的数据源都是 GBK格式的,不管是JavaScript调用还是PHP调用都要转换一下编码,不然得到的是乱码。而更需要注意的是,如果一次性查询多个IP,使用门户 网站的API来查询会非常缓慢,我大概写了个for循环试了下,不管是用PHP解析XML还是file_get_contents()函数获取内容,查询 10次以上会变得非常缓慢,甚至可能超时。
腾讯的IP地址API接口地址:http://fw.qq.com/ipaddress,返回的是数据格式为:var IPData = new Array("123.124.2.85","","北京市","");,一个JavaScript的对象,目前还不知道如何输入IP查询。
新浪的IP地址查询接口:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js
新浪多地域测试方法:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=123.124.2.85
网易有道的IP地址查询接口:http://www.youdao.com/smartresult-xml/search.s?type=ip&q=123.124.2.85
//腾讯API的PHP调用方法
$ip=file_get_contents("http://fw.qq.com/ipaddress");
$ip=str_replace('"',' ',$ip);
$ip2=explode("(",$ip);
$a=substr($ip2[1],0,-2);
$b=explode(",",$a);
return $b;
}
$ip=getIpPlace();
print_r($ip);
//有道API的PHP调用方法
$doc = new DOMDocument();
$doc->load($url);
$smartresult = $doc->getElementsByTagName("product");
foreach($smartresult as $product)
{
$locations = $product->getElementsByTagName("location");
$location = $locations->item(0)->nodeValue;
}
if($location != "")
{
echo $i.".".$ip;
echo " 来自".$location."的网友";
}
else
{
echo $i.".".$ip;
echo " 来自火星的网友";
}
public function sinaIPApi($ip){
$str = file_get_contents("http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=".$ip);
$str = iconv("gbk", "utf-8//IGNORE", $str);
preg_match_all("/[/x{4e00}-/x{9fa5}]+/u",$str,$get);
$add = implode('',$get[0]);
return $add;
}
//$get是一个非常棒的二维数组
其中有道和新浪的是我自己写的,新浪API也可以像腾讯API那样用file_get_contents()函数获取完地址后使用一连串的字符串函 数处理,我写的函数使用正则表达式从新浪的返回结果中提供包含中文的字符串,并且分段存入一个二维数组,这个可能只是针对新浪的API有用并且存在 bug。举个例子查询学校分配给我的IP地址后var_dump()一下函数里面的$get变量得到以下结果: array(1) { [0]=> array(6) { [0]=> string(6) "中国" [1]=> string(6) "北京" [2]=> string(6) "北京" [3]=> string(9) "教育网" [4]=> string(6) "学校" [5]=> string(18) "中国地质大学" } },而函数输出的结果则是“中国北京北京教育网学校中国地质大学”,希望我的思路和方法能对别人有用。
最后再次提醒,如果是WordPress请使用第一种方法,否则使用API同时查询所有留言者的真实地址会让PHP超时的,希望各路大牛有更好的方 法,至于限制显示和显示方式等神马的都是WordPress应用问题,同时对于Java和C#来说思路也是一样的,这些后续的问题等我考完试再细说。
PHP转换IP地址到真实地址的方法详解的更多相关文章
- 交换机工作原理、MAC地址表、路由器工作原理详解
一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理了,因为交换机是根据MAC地址表转发数据帧的.在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表,交换机就是根据 ...
- IPv6地址表示方法详解
IPv6是互联网协议的第六版:最初它在IETF的 IPng选取过程中胜出时称为互联网新一代网际协议(IPng),IPv6是被正式广泛使用的第二版互联网协议. 现有标准IPv4只支持大概40亿(4×10 ...
- TCP/IP、UDP、HTTP、SOCKET详解
文章大纲 网络OSI七层及各层作用 TCP与UDP基本介绍 TCP连接过程详解 SOCKET原理与连接详解 一.网络OSI七层及各层作用 应用层:文件传输,电子邮件,文件服务,虚拟终端 T ...
- linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解
最近要涉及对接现有应用visual c++开发的tcp客户端,花时间了解了下windows下tcp开发和linux的差别,从开发的角度而言,最大的差别是头文件(早期为了推广尽可能兼容,后面越来越扩展, ...
- PHP实现IP访问限制及提交次数的方法详解
一.原理 提交次数是肯定要往数据库里写次数这个数据的,比如用户登陆,当用户出错时就忘数据库写入出错次数1,并且出错时间,再出错写2,当满比如5次时提示不允许再登陆,请明天再试,然后用DateDiff计 ...
- 在Linux终端中查看公有IP的方法详解
首先回顾一下一般的查看IP的命令: ifconfigLinux查看IP地址的命令--ifconfigifconfig命令用于查看和更改网络接口的地址和参数 $ifconfig -a lo0: fla ...
- CentOS7网卡设置为桥接模式静态IP配置方法详解
备份网络文件 [root@localhost network-scripts]# cd /etc/sysconfig/network-scripts/ [root@localhost network- ...
- 【传输协议】TCP、IP协议族之数字签名与HTTPS详解
文章转载出自:https://blog.51cto.com/11883699/2160032 安全的获取公钥 细心的人可能已经注意到了如果使用非对称加密算法,我们的客户端A,B需要一开始就持有公钥,要 ...
- TCP/IP协议族(三) 数字签名与HTTPS详解
前面几篇博客聊了HTTP的相关东西,今天就来聊一聊HTTPS的东西.因为HTTP协议本身存在着明文传输.不能很好的验证通信方的身份和无法验证报文的完整性等一些安全方面的确点,所以才有了HTTPS的缺陷 ...
随机推荐
- hdu4696 想法题
就像1.2元人民币可以凑成任意你想要的面值一样.由于一定会有环,只要有C[i] == 1 就可以造成任何数.够坑吧 #include <cstdio> #include <cstri ...
- awr报告
BEGIN DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT();END;/ exec DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT ...
- HDOJ 5184 Brackets 卡特兰数扩展
既求从点(0,0)仅仅能向上或者向右而且不穿越y=x到达点(a,b)有多少总走法... 有公式: C(a+b,min(a,b))-C(a+b,min(a,b)-1) /// 折纸法证明卡特兰数: h ...
- poj--1579--(DFS+记忆化搜索之经典)
记忆化搜索 记忆化搜索:算法上依然是搜索的流程,但是搜索到的一些解用 动态规划的那种思想和模式作一些保存. 一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态. 更重要的是搜索还可以 ...
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
http://blog.csdn.net/pi9nc/article/details/23334659 注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料 ...
- 实现自己的cp命令
1 综述 在Unix和Linux系统里,cp是经常使用的一个命令,用于复制文件,用法如下: $cp src_file dest_file 以下就使用若干系统调用来实现自己的cp. 2 原理 open: ...
- [转] Linux下查看文件和文件夹大小
当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择. df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能为力. du可以查看文件及文件夹的大小. ...
- Android Studio学习随笔-模拟耗时操作(sleep)
在这里我申明一点,因为我是挂着VPN去YOUTOBE看的尚学堂的高明鑫老师讲的Android基础学习视频,有些东西他没有讲,而我也没办法,只能等两个星期后学校请老师来的时候进行询问,当然我也会将一些问 ...
- linux命令行计算器 <转>
转自 http://blog.chinaunix.net/uid-26959241-id-3207711.html 详细文档请 man bc 在windows下,大家都知道直接运行calc,(c:\w ...
- python之路,Day24 常用设计模式学习
python之路,Day24 常用设计模式学习 本节内容 设计模式介绍 设计模式分类 设计模式6大原则 1.设计模式介绍 设计模式(Design Patterns) --可复用面向对象软件的基础 ...