IP查询的方法(PHP和C#)
来源:互联网 发布:蔡晓红淘宝 编辑:程序博客网 时间:2024/06/06 02:08
首先下载最新的:(纯真)qqwry.dat文件
C #中的使用方法:
class IPHelper { FileStream ipFile; long ip; string ipfilePath; ///<summary> /// 构造函数 ///</summary> ///<param name="ipfilePath">纯真IP数据库路径</param> public IPHelper(string ipfilePath) { this.ipfilePath = ipfilePath; } ///<summary> /// 地理位置,包括国家和地区 ///</summary> public struct IPLocation { public string country, area; } ///<summary> /// 获取指定IP所在地理位置 ///</summary> ///<param name="strIP">要查询的IP地址</param> ///<returns></returns> public IPLocation GetIPLocation(string strIP) { ip = IPToLong(strIP); ipFile = new FileStream(ipfilePath, FileMode.Open, FileAccess.Read); long[] ipArray = BlockToArray(ReadIPBlock()); long offset = SearchIP(ipArray, 0, ipArray.Length - 1) * 7 + 4; ipFile.Position += offset;//跳过起始IP ipFile.Position = ReadLongX(3) + 4;//跳过结束IP IPLocation loc = new IPLocation(); int flag = ipFile.ReadByte();//读取标志 if (flag == 1)//表示国家和地区被转向 { ipFile.Position = ReadLongX(3); flag = ipFile.ReadByte();//再读标志 } long countryOffset = ipFile.Position; loc.country = ReadString(flag); if (flag == 2) { ipFile.Position = countryOffset + 3; } flag = ipFile.ReadByte(); loc.area = ReadString(flag); ipFile.Close(); ipFile = null; return loc; } ///<summary> /// 将字符串形式的IP转换位long ///</summary> ///<param name="strIP"></param> ///<returns></returns> public long IPToLong(string strIP) { byte[] ip_bytes = new byte[8]; string[] strArr = strIP.Split(new char[] { '.' }); for (int i = 0; i < 4; i++) { ip_bytes[i] = byte.Parse(strArr[3 - i]); } return BitConverter.ToInt64(ip_bytes, 0); } ///<summary> /// 将索引区字节块中的起始IP转换成Long数组 ///</summary> ///<param name="ipBlock"></param> long[] BlockToArray(byte[] ipBlock) { long[] ipArray = new long[ipBlock.Length / 7]; int ipIndex = 0; byte[] temp = new byte[8]; for (int i = 0; i < ipBlock.Length; i += 7) { Array.Copy(ipBlock, i, temp, 0, 4); ipArray[ipIndex] = BitConverter.ToInt64(temp, 0); ipIndex++; } return ipArray; } ///<summary> /// 从IP数组中搜索指定IP并返回其索引 ///</summary> ///<param name="ipArray">IP数组</param> ///<param name="start">指定搜索的起始位置</param> ///<param name="end">指定搜索的结束位置</param> ///<returns></returns> int SearchIP(long[] ipArray, int start, int end) { int middle = (start + end) / 2; if (middle == start) return middle; else if (ip < ipArray[middle]) return SearchIP(ipArray, start, middle); else return SearchIP(ipArray, middle, end); } ///<summary> /// 读取IP文件中索引区块 ///</summary> ///<returns></returns> byte[] ReadIPBlock() { long startPosition = ReadLongX(4); long endPosition = ReadLongX(4); long count = (endPosition - startPosition) / 7 + 1;//总记录数 ipFile.Position = startPosition; byte[] ipBlock = new byte[count * 7]; ipFile.Read(ipBlock, 0, ipBlock.Length); ipFile.Position = startPosition; return ipBlock; } ///<summary> /// 从IP文件中读取指定字节并转换位long ///</summary> ///<param name="bytesCount">需要转换的字节数,主意不要超过8字节</param> ///<returns></returns> long ReadLongX(int bytesCount) { byte[] _bytes = new byte[8]; ipFile.Read(_bytes, 0, bytesCount); return BitConverter.ToInt64(_bytes, 0); } ///<summary> /// 从IP文件中读取字符串 ///</summary> ///<param name="flag">转向标志</param> ///<returns></returns> string ReadString(int flag) { if (flag == 1 || flag == 2)//转向标志 ipFile.Position = ReadLongX(3); else ipFile.Position -= 1; List<byte> list = new List<byte>(); byte b = (byte)ipFile.ReadByte(); while (b > 0) { list.Add(b); b = (byte)ipFile.ReadByte(); } return Encoding.Default.GetString(list.ToArray()); } }调用如下:
static void Main(string[] args) { string ipfilePath = @"D:\qqwry.dat"; IPHelper IPHelper = new IPHelper(ipfilePath); string ip = "72.51.27.51"; IPHelper.IPLocation loc = IPHelper.GetIPLocation(ip); Console.WriteLine("你查的ip是:{0} 地理位置:{1} {2}", ip, loc.country, loc.area); Console.ReadKey(); }
PHP中使用:
<?php header("content-type:text/html;charset=gb2312");//*//文件头 [第一条索引的偏移量 (4byte)] + [最后一条索引的偏移地址 (4byte)] 8字节//记录区 [结束ip (4byte)] + [地区1] + [地区2] 4字节+不定长//索引区 [开始ip (4byte)] + [指向记录区的偏移地址 (3byte)] 7字节//注意:使用之前请去网上下载纯真IP数据库,并改名为 "CoralWry.dat" 放到当前目录下即可.//by 查询吧 www.query8.com//*class ipLocation {var $fp;var $firstip; //第一条ip索引的偏移地址var $lastip; //最后一条ip索引的偏移地址var $totalip; //总ip数//*//构造函数,初始化一些变量//$datfile 的值为纯真IP数据库的名子,可自行修改.//*function ipLocation($datfile = "qqwry.dat"){ $this->fp=fopen($datfile,'rb'); //二制方式打开 $this->firstip = $this->get4b(); //第一条ip索引的绝对偏移地址 $this->lastip = $this->get4b(); //最后一条ip索引的绝对偏移地址 $this->totalip =($this->lastip - $this->firstip)/7 ; //ip总数 索引区是定长的7个字节,在此要除以7, register_shutdown_function(array($this,"closefp")); //为了兼容php5以下版本,本类没有用析构函数,自动关闭ip库.}//*//关闭ip库//*function closefp(){fclose($this->fp);}//*//读取4个字节并将解压成long的长模式//*function get4b(){ $str=unpack("V",fread($this->fp,4)); return $str[1];}//*//读取重定向了的偏移地址//*function getoffset(){ $str=unpack("V",fread($this->fp,3).chr(0)); return $str[1];}//*//读取ip的详细地址信息//*function getstr(){ $split=fread($this->fp,1); $str=""; while (ord($split)!=0) { $str.=$split; $split=fread($this->fp,1); } return $str;}//*//将ip通过ip2long转成ipv4的互联网地址,再将他压缩成big-endian字节序//用来和索引区内的ip地址做比较//*function iptoint($ip){ return pack("N",intval(ip2long($ip)));}//*//获取客户端ip地址//注意:如果你想要把ip记录到服务器上,请在写库时先检查一下ip的数据是否安全.//*function getIP() { if (getenv('HTTP_CLIENT_IP')) { $ip = getenv('HTTP_CLIENT_IP'); } elseif (getenv('HTTP_X_FORWARDED_FOR')) { //获取客户端用代理服务器访问时的真实ip 地址 $ip = getenv('HTTP_X_FORWARDED_FOR'); } elseif (getenv('HTTP_X_FORWARDED')) { $ip = getenv('HTTP_X_FORWARDED'); } elseif (getenv('HTTP_FORWARDED_FOR')) { $ip = getenv('HTTP_FORWARDED_FOR'); } elseif (getenv('HTTP_FORWARDED')) { $ip = getenv('HTTP_FORWARDED'); } else { $ip = $_SERVER['REMOTE_ADDR']; } return $ip;}//*//获取地址信息//*function readaddress(){ $now_offset=ftell($this->fp); //得到当前的指针位址 $flag=$this->getflag(); switch (ord($flag)){ case 0: $address=""; break; case 1: case 2: fseek($this->fp,$this->getoffset()); $address=$this->getstr(); break; default: fseek($this->fp,$now_offset); $address=$this->getstr(); break; } return $address;}//*//获取标志1或2//用来确定地址是否重定向了.//*function getflag(){ return fread($this->fp,1);}//*//用二分查找法在索引区内搜索ip//*function searchip($ip){ $ip=gethostbyname($ip); //将域名转成ip $ip_offset["ip"]=$ip; $ip=$this->iptoint($ip); //将ip转换成长整型 $firstip=0; //搜索的上边界 $lastip=$this->totalip; //搜索的下边界 $ipoffset=$this->lastip; //初始化为最后一条ip地址的偏移地址 while ($firstip <= $lastip){ $i=floor(($firstip + $lastip) / 2); //计算近似中间记录 floor函数记算给定浮点数小的最大整数,说白了就是四舍五也舍 fseek($this->fp,$this->firstip + $i * 7); //定位指针到中间记录 $startip=strrev(fread($this->fp,4)); //读取当前索引区内的开始ip地址,并将其little-endian的字节序转换成big-endian的字节序 if ($ip < $startip) { $lastip=$i - 1; } else { fseek($this->fp,$this->getoffset()); $endip=strrev(fread($this->fp,4)); if ($ip > $endip){ $firstip=$i + 1; } else { $ip_offset["offset"]=$this->firstip + $i * 7; break; } } } return $ip_offset;}//*//获取ip地址详细信息//*function getaddress($ip){ $ip_offset=$this->searchip($ip); //获取ip 在索引区内的绝对编移地址 $ipoffset=$ip_offset["offset"]; $address["ip"]=$ip_offset["ip"]; fseek($this->fp,$ipoffset); //定位到索引区 $address["startip"]=long2ip($this->get4b()); //索引区内的开始ip 地址 $address_offset=$this->getoffset(); //获取索引区内ip在ip记录区内的偏移地址 fseek($this->fp,$address_offset); //定位到记录区内 $address["endip"]=long2ip($this->get4b()); //记录区内的结束ip 地址 $flag=$this->getflag(); //读取标志字节 switch (ord($flag)) { case 1: //地区1地区2都重定向 $address_offset=$this->getoffset(); //读取重定向地址 fseek($this->fp,$address_offset); //定位指针到重定向的地址 $flag=$this->getflag(); //读取标志字节 switch (ord($flag)) { case 2: //地区1又一次重定向, fseek($this->fp,$this->getoffset()); $address["area1"]=$this->getstr(); fseek($this->fp,$address_offset+4); //跳4个字节 $address["area2"]=$this->readaddress(); //地区2有可能重定向,有可能没有 break; default: //地区1,地区2都没有重定向 fseek($this->fp,$address_offset); //定位指针到重定向的地址 $address["area1"]=$this->getstr(); $address["area2"]=$this->readaddress(); break; } break; case 2: //地区1重定向 地区2没有重定向 $address1_offset=$this->getoffset(); //读取重定向地址 fseek($this->fp,$address1_offset); $address["area1"]=$this->getstr(); fseek($this->fp,$address_offset+8); $address["area2"]=$this->readaddress(); break; default: //地区1地区2都没有重定向 fseek($this->fp,$address_offset+4); $address["area1"]=$this->getstr(); $address["area2"]=$this->readaddress(); break; } //*过滤一些无用数据 if (strpos($address["area1"],"CZ88.NET")!=false){ $address["area1"]="未知"; } if (strpos($address["area2"],"CZ88.NET")!=false){ $address["area2"]=" "; } return $address; } }//测试一把$t = new ipLocation;$result = $t->getaddress('72.51.27.51');print_r($result);echo $result[' area1'];//*ipLocation class end?>
- IP查询的方法(PHP和C#)
- 华为查询ip的方法
- php和mysql关于ip段查询
- php显示mac地址和IP地址的方法
- php 时间格式设置和登陆获取ip的方法
- php获取ip的方法
- php获取ip的方法
- 验证IP的方法 (c#)
- PHP的IP地址查询库 QQWry
- IP地址转换为整型数字的PHP方法、Asp方法和MsSQL方法、MySQL方法
- [php]ip地址查询
- 纯真ip数据库查询的php实现(补充分组查询)
- QQwry.dat格式分析和查询IP位置的PHP程序
- QQwry.dat格式分析和查询IP位置的PHP程序
- ORACLE查询所有客户端的IP方法
- 查询外网IP地址的方法
- 获取Socket的本地IP端口和远程IP端口的方法(C++)
- 公网IP查询方法
- c++Primer笔记(一,二)
- 基于Fragment,Loader,Actionbar的几个好文章转载 1
- myEclipse svn安装
- scp
- PHP也玩并发,巧用curl 并发减少后端访问时间
- IP查询的方法(PHP和C#)
- svn工作原理以及服务搭建和配置
- 大型网站架构演变和知识体系
- 游戏开发中尽量不要做的一些事(技术,策划以及测试)
- 【转】玩转Google开源C++单元测试框架Google Test系列(gtest)之一 - 初识gtest
- 各种数转换成字符串
- C++ mfc学习之路二 网页按钮启动应用程序
- /proc/sysrq-trigger文件的强大功能
- SQL重复记录查询