什么是IP地址?
IP地址
IP地址是IP协议中还有一个非常重要的内容,那就是给因特网上的每台计算机和其它设备都规定了一个唯一的地址,叫做“IP地址”。由于有这种唯一的地址,才保证了用户在连网的计算机上操作时,能够高效而且方便地从千千万万台计算机中选出自己所需的对象来。
IP地址就像是我们的家庭住址一样,如果你要写信给一个人,你就要知道他(她)的地址,这样邮递员才能把信送到。计算机发送信息就好比是邮递员,它必须知道唯一的“家庭地址”才能不至于把信送错人家。只不过我们的地址是用文字来表示的,计算机的地址用二进制数字表示。
如何查看我们的IP地址呢
首先我们需要了解 两个概念:
公网IP:
公网也称外网,互联网,公网IP地址是分配给连接到 Internet 的设备的地址。要连接到 Internet,设备必须具有唯一的IP地址,以允许其他节点和设备找到它并建立连接。公共IP地址可以分配给Web服务器、电子邮件服务器,甚至是个人的个人计算机。
私网IP:
私网也称局域网,内网,私网IP地址是您的网络路由器分配给您的设备的地址。同一网络中的每个设备都分配有一个唯一的私有 IP 地址(有时称为私有网络地址)——这是同一内部网络中的设备相互通信的方式。
简单来说:我们平常家里连接使用的WIFI,校园连接的WIFI使用的都是内网IP,我们进行网页访问的时候,是要将私网ip转换为公网ip的,而路由器的主要工作就是这个,那么我们使用的运营商网络4G、5G又属于什么呢,查询我们手机上的运营商网络IP,一般会有两个IP一个是Ipv4另一个是Ipv6,以100开头,这个是Ipv4,输入到ip查询会显示到 运营商及NAT保留IP地址,另外一个Ipv6我们可以通过它查询到我们的体位置信息,也就是说现在我们使用的移动网络事实上还是属于内网的,运营商网络是使用的类似与路由器的网络设备将我们的网络形成了局域网,通过NAT技术实现网络通信,为什么要使用这种方式,主要原因是Ipv4地址已经枯竭,通俗点理解就是我们使用的运营商网络不会为我们单独分配公网ip,我们使用的是私网ip,多个用户共用一个公网ip进行网络访问。
如何进行私网ip地址查看:
如果我们使用的是WIFI那么很简单,只需要点击WIFI详情就可以看到,这里我们查询到的是私网ip,手机上也是相同的原理,我们连接WIFI时的ip地址也是私网IP。但是通过私网ip我们是无法查询到具体的位置的,需要获取公网ip。
获取ip地址
网络上很多获取ip地址方式都是只获取了内网ip,事实上意义不大,我们这里推荐一种获取外网ip的简单的方式。
使用第三方API,通过第三方接口我们可以很容易获取我们的外网ip,好处是网上接口多,容易找到,缺点是API接口存在失效的可能性,这里我推荐三个API接口:
1.只获取IP地址
http://ip.json-json.com/
2.能获取省份信息,ip地址,网络运营商
https://gamematrix.qq.com/sdk/v2/get_gateway
3.能获取ip地址,获取的其他信息有误(不建议)
http://pv.sohu.com/cityjson
这个接口在电脑端获取的ip是正确的,但是获取的ip属地是错误的,用这个接口获取一下ip地址就可以了,有了ip地址我们可以得到很多信息。
下面演示我们的第一种方式:
这种获取ip的原理很简单,直接从接口中获取JSON数据转换成字符串即可,因为这个接口返回的就是ip地址我们直接返回就行,不需要对Json数据进行额外的取key操作,这了用了阿里巴巴的fastjson 要导入依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.2.3</version>
<classifier>jdk15</classifier><!-- 指定jdk版本 -->
</dependency>
import net.sf.json.JSONObject;
import org.lionsoul.ip2region.xdb.Searcher;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.concurrent.TimeUnit;
// 获取本机ip
public class IpUtil {
//获取Json数据
public static String getIp(String url) {
StringBuilder json0 = new StringBuilder();
try {
URL urlObject = new URL(url);
//从地址中获取数据
URLConnection uc = urlObject.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream(),"utf-8"));
String inputLine = null;
while ( (inputLine = in.readLine()) != null) {//按行读取
json0.append(inputLine);
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return json0.toString();
}
测试:
@Test
public void testIPUtils(){
String ip1 = IpUtil.getIp("http://ip.json-json.com/");
String ip2 = IpUtil.getIp("https://gamematrix.qq.com/sdk/v2/get_gateway");
String ip3 = IpUtil.getIp3();
System.out.println("方式一"+ip1);
System.out.println("方式二"+ip2);
System.out.println("方式三"+ip3);
}
结果:
上百度查看我们获取的ip是否正确
成功获取了ip地址。
获取ip属地:
我们通过上文的https://gamematrix.qq.com/sdk/v2/get_gateway就已经可以获取ip地址了,不过显示到的是省份,下面我们介绍两种获取ip属地的方式,国内详细到市,国外显示国家。
测试以ip:112.67.251.91为例
百度查询:
方式一:IP地址库ip2region
推荐使用GitHub上免费的开源地址库,ip2region,简单好用,支持:java、C#、php、c、python、nodejs、php扩展(php5和php7)、golang、rust、lua、lua_c, nginx
GitHub地址:https://github.com/lionsoul2014/ip2region
如何使用:
官方文档:https://github.com/lionsoul2014/ip2region/tree/master/binding/java
第一步:找到数据库文件,ip2region.xdb,文件在data里
将文件放到我们的resource中
第二步,导入依赖在pom.xml:
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.6.5</version>
</dependency>
第三步编写IpUtil类:
//方式一:使用ip2region获取Ip属地
public static String ipAddress(String ip) {
String dbPath = "";
//读取文件
File file = new File("src/main/resources/ip2region.xdb");
dbPath = file.getPath();
String region = "";
Searcher searcher = null;
try {
searcher = Searcher.newWithFileOnly(dbPath);
} catch (IOException e) {
System.out.printf("failed to create searcher with `%s`: %s\n", dbPath, e);
return "文件未找到";
}
// 2、查询
try {
long sTime = System.nanoTime();
//查询ip属地
region = searcher.search(ip);
long cost = TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() - sTime));
System.out.printf("{region: %s, ioCount: %d, 耗时: %d μs}\n", region, searcher.getIOCount(), cost);
} catch (Exception e) {
System.out.printf("failed to search(%s): %s\n", ip, e);
}
// 3、关闭资源
try {
searcher.close();
} catch (IOException e) {
e.printStackTrace();
}
return region;
}
测试:
@Test
public void testIPUtils1(){
String ipAddress = "112.67.251.91";
System.out.println(IpUtil.ipAddress(ipAddress));
}
结果:
这种基于ip属地库的查询方式效率高于第三方接口,不需要给第三放接口发送请求,节省时间。
方式二:使用第三方API
原理和获取ip地址的原理相同,这里我们推荐两个ip属地查询接口:
//使用百度ip地址查询API
String ipAddressAPI1 = "http://opendata.baidu.com/api.php?query="+ip+"&co=&resource_id=6006&oe=utf8";
//使用太平洋ip地址查询API
String ipAddressAPI2 = "http://whois.pconline.com.cn/ipJson.jsp?ip=+"+ip+"&json=true";
获取地址方法:
//方式二:使用IP归属地查询API
public static String getIpAddress2(String ip){
//使用百度ip地址查询API
String ipAddressAPI1 = "http://opendata.baidu.com/api.php?query="+ip+"&co=&resource_id=6006&oe=utf8";
//使用太平洋ip地址查询API
String ipAddressAPI2 = "http://whois.pconline.com.cn/ipJson.jsp?ip=+"+ip+"&json=true";
StringBuilder json = new StringBuilder();
try {
URL urlObject = new URL(ipAddressAPI1);
//2.从地址中获取数据
URLConnection uc = urlObject.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream(),"utf-8"));
String inputLine = null;
while ( (inputLine = in.readLine()) != null) {//按行读取
json.append(inputLine);
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return json.toString();
}
测试:
@Test
public void testIPUtils2(){
String ipAddress = IpUtil.getIpAddress2("112.67.251.91");
System.out.println("原始数据"+ipAddress);//原始数据
JSONObject jsonObject1 = JSON.parseObject(ipAddress);
System.out.println(jsonObject1);
//Json数据含有数组,先获取数组
JSONArray data = jsonObject1.getJSONArray("data");
//获取数组data第一个数据
JSONObject JsonData=(JSONObject) data.get(0);
Object location = JsonData.get("location");
System.out.println(location);
}
测试结果:
第三放查询ip属地API也是一种不错的方式,需要注意的问题是接口可能会失效,接口对查询次数可能存在限制。