通过IpLocatoin.php(ip处理类) 及qqwry.dat(IP纯真),完整获取ip对应的详细地址

Tp5.1通过ip获取地址

public function getAddress(){$ip = request()->ip();$IpLocation = new IpLocation();$findProvince = $IpLocation->getlocation($ip);if($findProvince){$str = $findProvince['country'].'('.$findProvince['area'].')';}else{$str = "未知";}return $str;
}

地址处理类--需配合IP纯真库*(qqwry.dat)使用

<?php
namespace app\index\controller;
/** * IP 地理位置查询类 */
class IpLocation
{  /** * QQWry.Dat文件指针 * * @var resource */  private $fp;  /** * 第一条IP记录的偏移地址 * * @var int */  private $firstip;  /** * 最后一条IP记录的偏移地址 * * @var int */  private $lastip;  /** * IP记录的总条数(不包含版本信息记录) * * @var int */  private $totalip;  /** * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息 * * @param string $filename */  public function __construct()  {  $filename = './static/other/qqwry.dat';$this->fp = 0;  if (($this->fp = fopen($filename, 'rb')) !== false) {  $this->firstip = $this->getlong();  $this->lastip = $this->getlong();  $this->totalip = ($this->lastip - $this->firstip) / 7;  //注册析构函数,使其在程序执行结束时执行  register_shutdown_function(array(  &$this,  '__destruct'  ));  }  }  /** * 析构函数,用于在页面执行结束后自动关闭打开的文件。 * */  public function __destruct()  {  if ($this->fp) {  fclose($this->fp);  }  $this->fp = 0;  }  /** * 返回读取的长整型数 * * @access private * @return int */  private function getlong()  {  //将读取的little-endian编码的4个字节转化为长整型数  $result = unpack('Vlong', fread($this->fp, 4));  return $result['long'];  }  /** * 返回读取的3个字节的长整型数 * * @access private * @return int */  private function getlong3()  {  //将读取的little-endian编码的3个字节转化为长整型数  $result = unpack('Vlong', fread($this->fp, 3) . chr(0));  return $result['long'];  }  /** * 返回压缩后可进行比较的IP地址 * * @access private * @param string $ip * @return string */  private function packip($ip)  {  // 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False,  // 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串  return pack('N', intval(ip2long($ip)));  }  /** * 返回读取的字符串 * * @access private * @param string $data * @return string */  private function getstring($data = "")  {  $char = fread($this->fp, 1);  while (ord($char) > 0) { // 字符串按照C格式保存,以结束  $data .= $char; // 将读取的字符连接到给定字符串之后  $char = fread($this->fp, 1);  }  return iconv('gbk', 'utf-8', $data);  }  /** * 返回地区信息 * * @access private * @return string */  private function getarea()  {  $byte = fread($this->fp, 1); // 标志字节  switch (ord($byte)) {  case 0: // 没有区域信息  $area = "";  break;  case 1:  case 2: // 标志字节为1或2,表示区域信息被重定向  fseek($this->fp, $this->getlong3());  $area = $this->getstring();  break;  default: // 否则,表示区域信息没有被重定向  $area = $this->getstring($byte);  break;  }  return $area;  }  /** * 根据所给 IP 地址或域名返回所在地区信息 * * @access public * @param string $ip * @return array */  public function getlocation($ip)  {  if (!$this->fp)  return null; // 如果数据文件没有被正确打开,则直接返回空  $location['ip'] = gethostbyname($ip); // 将输入的域名转化为IP地址  $ip = $this->packip($location['ip']); // 将输入的IP地址转化为可比较的IP地址  // 不合法的IP地址会被转化为255.255.255.255  // 对分搜索  $l = 0; // 搜索的下边界  $u = $this->totalip; // 搜索的上边界  $findip = $this->lastip; // 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息)  while ($l <= $u) { // 当上边界小于下边界时,查找失败  $i = floor(($l + $u) / 2); // 计算近似中间记录  fseek($this->fp, $this->firstip + $i * 7);  $beginip = strrev(fread($this->fp, 4)); // 获取中间记录的开始IP地址  // strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式  // 以便用于比较,后面相同。  if ($ip < $beginip) { // 用户的IP小于中间记录的开始IP地址时  $u = $i - 1; // 将搜索的上边界修改为中间记录减一  } else {  fseek($this->fp, $this->getlong3());  $endip = strrev(fread($this->fp, 4)); // 获取中间记录的结束IP地址  if ($ip > $endip) { // 用户的IP大于中间记录的结束IP地址时  $l = $i + 1; // 将搜索的下边界修改为中间记录加一  } else { // 用户的IP在中间记录的IP范围内时  $findip = $this->firstip + $i * 7;  break; // 则表示找到结果,退出循环  }  }  }  //获取查找到的IP地理位置信息  fseek($this->fp, $findip);  $location['beginip'] = long2ip($this->getlong()); // 用户IP所在范围的开始地址  $offset = $this->getlong3();  fseek($this->fp, $offset);  $location['endip'] = long2ip($this->getlong()); // 用户IP所在范围的结束地址  $byte = fread($this->fp, 1); // 标志字节  switch (ord($byte)) {  case 1: // 标志字节为1,表示国家和区域信息都被同时重定向  $countryOffset = $this->getlong3(); // 重定向地址  fseek($this->fp, $countryOffset);  $byte = fread($this->fp, 1); // 标志字节  switch (ord($byte)) {  case 2: // 标志字节为2,表示国家信息又被重定向  fseek($this->fp, $this->getlong3());  $location['country'] = $this->getstring();  fseek($this->fp, $countryOffset + 4);  $location['area'] = $this->getarea();  break;  default: // 否则,表示国家信息没有被重定向  $location['country'] = $this->getstring($byte);  $location['area'] = $this->getarea();  break;  }  break;  case 2: // 标志字节为2,表示国家信息被重定向  fseek($this->fp, $this->getlong3());  $location['country'] = $this->getstring();  fseek($this->fp, $offset + 8);  $location['area'] = $this->getarea();  break;  default: // 否则,表示国家信息没有被重定向  $location['country'] = $this->getstring($byte);  $location['area'] = $this->getarea();  break;  }  if ($location['country'] == " CZ88.NET") { // CZ88.NET表示没有有效信息  $location['country'] = "未知";  }  if ($location['area'] == " CZ88.NET") {  $location['area'] = "";  }  return $location;  }
}

免费IP库下载

  • 纯真官网地址

  • 关注微信公众号(纯真IP实验室)下载

通过IpLocatoin.php(ip处理类) 及qqwry.dat(IP库),完整获取ip对应的详细地址

通过Ip纯真库获取地址详细信息相关推荐

  1. Go 使用IP纯真库获取IP对应的国家、省、市

    创作不易感谢支持. 一条主写Go和PHP的小菜鸟.平常有时间喜欢自己写点东西,如有不对的地方,欢迎大佬指点. 个人博客:太阳上的雨天 地址:blog.caixiaoxin.cn 善于分享,希望有助他人 ...

  2. Python3 | 通过百度地图API获取商家详细信息(包括店名,地址,经纬度,电话)

    一.打开百度地图开放平台,选择Web服务API . ​​​​​​官方文档对API接口的调用描述的比较详细,在调用之前先要申请百度地图的账号,然后申请密钥,获取密钥的步骤官方也有说明. 二.通过百度地图 ...

  3. PHP 获取服务器详细信息

    PHP 获取系统信息,PHP 获取服务器详细信息 获取系统类型及版本号:    php_uname()                                   (例:Windows NT ...

  4. 淘宝/天猫API接口,item_sku - 淘宝商品SKU详细信息查询,淘宝/天猫获取sku详细信息 API 返回值说明

    欢迎使用淘宝API接口(item_sku - 淘宝商品SKU详细信息查询 ) 你好! 这是你使用我们的淘宝API接口获取商品详细接口说明. 测试地址:获取Key和secret 测试结果: Reques ...

  5. 淘宝API接口:获取sku详细信息

    今天分享的是淘宝平台API,item_sku - 获取sku详细信息 点击注册测试地址(获取Key和secret) { "item": { "num_iid": ...

  6. 淘宝/天猫如何获取sku API接口,item_sku - 获取sku详细信息

    一.接口参数说明: 通过淘宝/天猫app中分享至PC端的短链接商品ID,通过调用item_sku - 获得sku接口,可以得到接口要的商品sku详情数据. 点击获取测试key和secret 请求地址: ...

  7. Android获取歌曲详细信息

    Android获取歌曲详细信息 一.目标 二.实现方案 三.HTML方案 四.JSON方案 五.接下来 六.Finally 在<Android实现歌词笔记构思>时,构思了如何在笔记中添加歌 ...

  8. Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息

    Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息 在此回复牛妞的关于程序中分词器的问题,其实可以直接很简单的在词库中配置就好了,Lucene中分词的所有信息我们都可以从 ...

  9. 微信小程序控制台 报错 对应的服务器证书无效 控制台输入 showRequestInfo() 可以获取更详细信息 原因是ssl证书过期 重新申请即可

    微信小程序控制台 报错 对应的服务器证书无效.控制台输入 showRequestInfo() 可以获取更详细信息 报错原因:域名下的SSL证书过期 我这边报错的原因是ssl证书过期 重新申请后就好了, ...

最新文章

  1. Android LayoutInflater 的使用
  2. git diff Git查看版本改动
  3. oracle错误:ORA-12545
  4. Hexo自定义页面的两种方法
  5. json数据映射到html,在GoLang中将Json数据映射到Html模板
  6. 卸载angular版本
  7. 05.analysis-normalizer应用
  8. Harvard-X免费生物信息课程 (代码、文档、数据) - 适合系统学习
  9. 阿里云服务器——centos7下源码安装tomcat9
  10. 如何在 Mac 上下载 macOS Monterey public beta 6?
  11. 【算法笔记+BZOJ3676】回文串(回文树/回文自动机模版题)
  12. json文件格式转换为png文件格式
  13. android 打好的补丁位置,Android 6.0上打完第一个补丁后再打新补丁Crash
  14. clickHouse 使用常见问题踩坑
  15. 详解vue原理之观察模式Dep->Watcher
  16. 重装linux后没声音,安装虚拟机后没声音了
  17. 芝加哥大学校长:诺贝尔奖人才是怎样炼成的?
  18. 淘宝/天猫API:item_recommend-获取推荐商品列表
  19. java生命之树_珍惜生命的心得感想与体会
  20. UE4引擎源码学习笔记(一):源码整体文件结构

热门文章

  1. 深度学习实战5-卷积神经网络(CNN)中文OCR识别项目
  2. 最近爆火的一款 PDF 神器!
  3. ZYNQ进阶之路14--PS端uart串口接收不定长数据
  4. 段码液晶屏发黑现象什么原因?
  5. 数十名员工和高管离开,谷歌支付陷入大动荡
  6. c和java哪个难_为什么说 C 语言比 Java 难?
  7. 今天开始学java,我会多看推荐的好书,多看干货博客,好好努力学习的!7个月哦,我在北大青鸟培训班,入门听老师的,其余的还是靠我自己自学吧,加油!
  8. 如何把粤康码行程卡拼图?小白拼图话你知
  9. 【计算机网络详解】——知识点复习(期末不挂科版)
  10. cocoscreator 浏览器调试技巧