在产品中可能存在不同客户端,请求同一个服务端接口的场景。

例如小程序和App或者浏览器中,如果需要对请求的归属地进行分析,前提是需要先获取请求所在的国家或城市,这种定位通常需要主动授权,而用户一般是不愿意提供的,就需要通过请求的IP来进行归属地计算。

IP地址一般分为两种,IPV4和IPV6,相应的计算方式也有差异,以国家维度来参考,每个国家都有对应的网段范围,计算网段中的最小和最大IP地址的对应数值,然后对比请求的IP地址,来判断属于哪个国家的网段范围。

import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.util.StrUtil;
import java.math.BigInteger;
import java.net.InetAddress; public class IpCalculate {
public static void main(String[] args) throws Exception {
// IPv4 网段
String ipv4Network = "IPv4 网段";
String[] ipv4Param = StrUtil.splitToArray(ipv4Network, "/"); // IPv4 起始和结束IP
String ipv4StartIp = Ipv4Util.getBeginIpStr(ipv4Param[0],Integer.parseInt(ipv4Param[1]));
String ipv4OverIp = Ipv4Util.getEndIpStr(ipv4Param[0],Integer.parseInt(ipv4Param[1]));
System.out.println(ipv4StartIp);
System.out.println(ipv4OverIp); // IPv4 起始和结束IP对应的Long值
System.out.println(Ipv4Util.ipv4ToLong(ipv4StartIp));
System.out.println(Ipv4Util.ipv4ToLong(ipv4OverIp)); // IPv6 网段
String ipv6Network = "IPv6 网段";
String[] ipv6Param =ipv6Network.split("/");
int prefixLength = Integer.parseInt(ipv6Param[1]); // IPv6 起始和结束IP
InetAddress baseAddress = InetAddress.getByName(ipv6Param[0]);
BigInteger baseValue = new BigInteger(1, baseAddress.getAddress());
BigInteger mask = BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE)
.shiftRight(128 - prefixLength).shiftLeft(128 - prefixLength);
BigInteger minIp = baseValue.and(mask);
BigInteger maxIp = minIp.add(BigInteger.ONE.shiftLeft(128 - prefixLength).subtract(BigInteger.ONE));
System.out.println(toIPv6String(minIp));
System.out.println(toIPv6String(maxIp)); // IPv6 起始和结束IP对应的Long值
System.out.println(minIp);
System.out.println(maxIp);
} private static String toIPv6String(BigInteger value) throws Exception {
byte[] bytes = value.toByteArray();
byte[] ipv6Bytes = new byte[16];
int start = bytes.length > 16 ? bytes.length - 16 : 0;
int length = Math.min(bytes.length, 16);
System.arraycopy(bytes, start, ipv6Bytes, 16 - length, length);
return InetAddress.getByAddress(ipv6Bytes).getHostAddress();
}
}

不过网段地址和国家的对应关系需要进行维护,如果归属地分析不需要非常精准,可以直接使用开源的字典库,比如使用比较多的就是GeoIP2组件。

<dependency>
<groupId>com.maxmind.geoip2groupId>
<artifactId>geoip2</artifactId>
</dependency>

通过组件中提供的API加载相应的文件字典,然后传入IP地址进行归属地判断,这里要注意争议和敏感地区的处理,如果出错产品可不止是上热搜的问题了。

import com.maxmind.geoip2.DatabaseReader;
import java.io.File;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress; public class GeoIpTool {
public static void main(String[] args) throws Exception { // 读取IP库文件
File ipFile = new File("IP文件库");
DatabaseReader reader = new DatabaseReader.Builder(ipFile).build(); // IPV4地址
InetAddress ipV4 = InetAddress.getByName("IPV4");
if (ipV4 instanceof Inet4Address){
System.out.println(reader.country(ipV4));
System.out.println(reader.country(ipV4).getCountry());
// 默认英文名
System.out.println(reader.country(ipV4).getCountry().getName());
// 查询中文名
System.out.println(reader.country(ipV4).getCountry().getNames().get("zh-CN"));
} // IPV6地址
InetAddress ipV6 = InetAddress.getByName("IPV6");
if (ipV6 instanceof Inet6Address){
System.out.println(reader.country(ipV6));
System.out.println(reader.country(ipV6).getCountry());
// 默认英文名
System.out.println(reader.country(ipV6).getCountry().getName());
// 查询中文名
System.out.println(reader.country(ipV6).getCountry().getNames().get("zh-CN"));
}
}
}

如果需要非常精确的实时归属地分析,可以购买专业的IP网段数据,实时更新到本地的数据库中,作为IP字典使用,获取请求的IP后,直接范围匹配即可。

CREATE TABLE `ip_place` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`network` varchar(100) DEFAULT NULL COMMENT '网段区间',
`min_ip` bigint(20) DEFAULT NULL COMMENT '最小IP',
`max_ip` bigint(20) DEFAULT NULL COMMENT '最大IP',
`min_ip_number` bigint(20) DEFAULT NULL COMMENT '最小IP数值',
`max_ip_number` bigint(20) DEFAULT NULL COMMENT '最大IP数值',
`ip_place` varchar(100) DEFAULT NULL COMMENT '归属地',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='IP归属地';

最后需要补充说一句,对于很多标准的数据,尽可能在项目最初就设计好字典枚举或者数据表,避免后续规范时面临数据清洗的问题。

通过IP计算分析归属地的更多相关文章

  1. TCP、UDP、IP 协议分析

    http://rabbit.xttc.edu.cn/rabbit/htm/artical/201091145609.shtml  http://bhsc881114.github.io/2015/06 ...

  2. TCP、UDP、IP协议分析

    此篇文章的原创作者是:草根老师博客(程姚根) chengyaogen.blog.chinaunix.net 感谢原作者! 互连网早期的时候,主机间的互连使用的是NCP协议.这种协议本身有很多缺陷,如: ...

  3. TCP/IP协议分析

    一;前言 学习过TCP/IP协议的人多有一种感觉,这东西太抽象了,没有什么数据实例,看完不久就忘了.本文将介绍一种直观的学习方法,利用协议分析工具学习TCP/IP,在学习的过程中能直观的看到数据的具体 ...

  4. TCP/IP协议分析(推荐)

    一;前言 学习过TCP/IP协议的人多有一种感觉,这东西太抽象了,没有什么数据实例,看完不久就忘了.本文将介绍一种直观的学习方法,利用协议分析工具学习TCP/IP,在学习的过程中能直观的看到数据的具体 ...

  5. [SuProxy]Ngnix+Lua 实现SSH2,LDAP,ORACLE,SQLSERVER等TCP/IP协议分析,劫持,代理,会话及负载

    目录 目录 目录 前言 介绍 安装 下载并拷贝 使用LuaRocks安装 运行测试 使用简介 处理器(processor)创建 通道(channel)创建 负载均衡 会话信息和会话管理 Event H ...

  6. floating IP 原理分析 - 每天5分钟玩转 OpenStack(107)

    上一节我们通过 Web UI 创建为 cirros-vm3 分配了浮动 IP,今天将分析其工作原理. 首先查看 router 的 interface 配置: 可以看到,floating IP 已经配置 ...

  7. Linux内核TCP/IP参数分析与调优

    转载于:http://www.itxuexiwang.com/a/liunxjishu/2016/0225/167.html?1456482565 如下图展示的是TCP的三个阶段.1,TCP三次握手. ...

  8. C# 根据IP查询地址归属地

    必备文件:IPLocation.dll.QQWry.Dat 下载地址:http://pan.baidu.com/s/1jG1dlOy (可百度下载) 之前有过将 QQWry.Dat 转为 Access ...

  9. tcpdump使用和TCP/IP包分析

    关于tcpdump如何抓包,本文不再总结,可以查看 tcpdump的官方地址查看http://www.tcpdump.org 本文重点记录两个部分:           第一部分:tcpdump所抓包 ...

  10. 软考计算机网络原理之IP计算问题汇总

    转自 http://www.cnblogs.com/jyh317/archive/2013/04/14/3018650.html 1.IP地址 分类: ①A类IP地址 ②B类IP地址 ③C类IP地址 ...

随机推荐

  1. Python实战:为Prometheus开发自定义Exporter

    Python实战:为Prometheus开发自定义Exporter 在当今的微服务架构和容器化部署环境中,监控系统的重要性不言而喻.Prometheus作为一款开源的系统监控和警报工具,以其强大的功能 ...

  2. IDEA 编辑java项目跳过测试

    一.Idea配置

  3. 揭秘 Sdcb Chats 如何解析 DeepSeek-R1 思维链

    在上一篇文章中,我介绍了 Sdcb Chats 如何集成 DeepSeek-R1 模型,并利用其思维链(Chain of Thought, CoT)功能增强 AI 推理的透明度.DeepSeek-R1 ...

  4. Git指南-从入门到精通

    代码提交和同步命令 流程图如下: 第零步: 工作区与仓库保持一致 第一步: 文件增删改,变为已修改状态 第二步: git add ,变为已暂存状态 $ git status $ git add --a ...

  5. Git钩子-每次提交信息添加分支名称

    Git钩子是一组脚本,这些脚本对应着Git仓库中的特定事件,每一次事件发生时,钩子会被触发.这允许你可以定制化Git的内部行为,在开发周期中的关键点上触发执行定制化的脚本. 钩子脚本文件通常放置于项目 ...

  6. 超详细,DeepSeep 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方DeepSeek接入),建议收藏!

    在当今数字化时代,AI编程助手已成为提升开发效率的利器.DeepSeek作为一款强大的AI模型,凭借其出色的性能和开源免费的优势,成为许多开发者的首选.今天,就让我们一起探索如何将DeepSeek接入 ...

  7. 解锁DeepSeek深度应用,天翼云GPU云主机强势破局!

    在人工智能重塑世界的当下,一场影响深远的科技变革正在悄然上演,DeepSeek系列模型在诸多领域掀起热潮.企业级AI模型的训练与部署,不仅是技术的角力场,更是决定企业兴衰的生死线.每一次算法的迭代革新 ...

  8. [BZOJ3159] 决战 题解

    个人感觉各方面难度高于<在美妙的数学王国中畅游>,也不知道是不是求导的关系,这题 \(luogu\) 难度评级还更低.不过感觉这题作完对 \(LCT\) 理解更顺畅了. 前四个操作简单,关 ...

  9. Jenkins - [02] 安装部署

    题记部分 一.Jenkins是什么   Jenkins,原名Hudson,2011年改为现在的名字,它是一个开源的实现持续集成的软件工具. 官网:https://www.jenkins.io/ 官网: ...

  10. @autowired注解报错原因及解决办法

    @autowired 注入dao层的时候,标红报错,但不影响编译使用 按照严格的spring注解方式在dao层加入@Repository注解