赞
踩
根据上篇文章的学习,大致看了看net包中提供的方法,然后通过网上搜索整理了一下各个知识点。
先声明下,我也是跟着网上的各种教程学习,并整理,只为记录、分享,不盈利,应该不涉及侵权。。。
一、在net包中InetAddress类中,提供了四个创建InetAddress对象的静态方法:
- getLocalHost() throws UnknownHostException 获取描述本机IP的InetAddress对象
- getByName(String host) throws UnknownHostException 通过指定域名从DNS中得到相应的IP地址
- getAllByName(String host) throws UnknownHostException 从DNS上得到域名对应的所有的IP。这个方法返回一个InetAddress类型的数组
- getByAddress(String host, byte[] addr) throws UnknownHostException 根据提供的主机名和IP地址创建一个InetAddress
- getByAddress(byte[] addr) throws UnknownHostException 获取给定原始IP地址的对象(这也属于第四个)
通过以上方法,可以直接创建地址对象。
二、getHostName方法和getCanonicalHostName方法
getCanonicalHostName方法和getHostName方法一样,也是得到远程主机的域名。但它们有一个区别,getCanonicalHostName得到的是主机名,而getHostName得到的主机别名。
之所以要使用主机别名,是因为有时主机名可能比较复杂,有很多网站通过主机名无法访问,只有通过一些别名才能访问,这是因为在服务端通过HTTP协议做了限制。
如果InetAddress对象是通过IP地址创建的,getCanonicalHostName方法和getHostName方法的值是完全一样的,它们的值可能是主机名,也可能是IP地址。而用域名创建的InetAddress对象就不一定了,它们的值可能相同(相同的IP地址或域名),也可能不相同,如上面运行结果中的www.126.com使用这两个方法得到的值就不同。在一般情况下,我们可以使用getHostName来获得域名,因为如果使用域名来创建InetAddress对象,getHostName所得到的域名就是用来创建InetAddress对象的域名,如果使用IP地址来创建InetAddress对象,getHostName方法等价于getCanonicalHostName方法。
三、getAddress方法和getHostAddress方法
getAddress方法和getHostAddress类似,它们的唯一区别是getHostAddress方法返回的是字符串形式的IP地址,而getAddress方法返回的是byte数组形式的IP地址。无论InetAddress对象是使用哪种方式创建的,getHostAddress方法都不会访问DNS服务器。
四、判断一个IP地址是否是一个特殊的IP地址的十个方法
1、isAnyLocalAddress方法
当IP地址是通配符地址时返回true,否则返回false。
这个通配符地址对于拥有多个网络接口(如两块网卡)的计算机非常拥有。使用通配符地址可以允许在服务器主机接受来自任何网络接口的客户端连接。IPv4的通配符地址是0.0.0.0。IPv6的通配符地址是0:0:0:0:0:0:0:0,也可以简写成::。
2、isLoopbackAddress方法
当IP地址是loopback地址时返回true,否则返回false。loopback地址就是代表本机的IP地址。
IPv4的loopback地址的范围是127.0.0.0 ~ 127.255.255.255,也就是说,只要第一个字节是127,就是lookback地址。如127.1.2.3、127.0.200.200都是loopback地址。IPv6的loopback地址是0:0:0:0:0:0:0:1,也可以简写成::1。我们可以使用ping命令来测试lookback地址。如下面的命令行所示:ping 127.200.200.200
虽然127.255.255.255也是loopback地址,但127.255.255.255在Windows下是无法ping通的。这是因为127.255.255.255是广播地址,在Windows下对发给广播地址的请求不做任何响应,而在其他操作系统上根据设置的不同,可能会得到不同的结果。
3、isLinkLocalAddress方法
当IP地址是本地连接地址(LinkLocalAddress)时返回true,否则返回false。
IPv4的本地连接地址的范围是169.254.0.0 ~ 169.254.255.255。IPv6的本地连接地址的前12位是FE8,其他的位可以是任意取值,如FE88::、FE80::ABCD::都是本地连接地址。
4、isSiteLocalAddress方法
当IP地址是地区本地地址(SiteLocalAddress)时返回true,否则返回false。
IPv4的地址本地地址分为三段:10.0.0.0 ~ 10.255.255.255、172.16.0.0 ~ 172.31.255.255、192.168.0.0 ~ 192.168.255.255。IPv6的地区本地地址的前12位是FEC,其他的位可以是任意取值,如FED0::、FEF1::都是地区本地地址。
5、isMulticastAddress方法
当IP地址是广播地址(MulticastAddress)时返回true,否则返回false。
通过广播地址可以向网络中的所有计算机发送信息,而不是只向一台特定的计算机发送信息。IPv4的广播地址的范围是224.0.0.0 ~ 239.255.255.255。IPv6的广播地址第一个字节是FF,其他的字节可以是任意值。
6、isMCGlobal方法
当IP地址是全球范围的广播地址时返回true,否则返回false。
全球范围的广播地址可以向Internet中的所有的计算机发送信息。IPv4的广播地址除了224.0.0.0和第一个字节是239的IP地址都是全球范围的广播地址。IPv6的全球范围的广播地址中第一个字节是FF,第二个字节的范围是0E ~ FE,其他的字节可以是任意值,如FFBE::、FF0E::都是全球范围的广播地址。
7、isMCLinkLocal方法
当IP地址是子网广播地址时返回true,否则返回false。
使用子网的广播地址只能向子网内的计算机发送信息。IPv4的子网广播地址的范围是224.0.0.0 ~ 224.0.0.255。IPv6的子网广播地址的第一个字节是FF,第二个字节的范围是02 ~ F2,其他的字节可以是任意值,如FFB2::、FF02:ABCD::都是子网广播地址。
8、isMCNodeLocal方法
当IP地址是本地接口广播地址时返回true,否则返回false。
本地接口广播地址不能将广播信息发送到产生广播信息的网络接口,即使是同一台计算机的另一个网络接口也不行。所有的IPv4广播地址都不是本地接口广播地址。IPv6的本地接口广播地址的第一个字节是FF,第二个节字的范围是01 ~ F1,其他的字节可以是任意值,如FFB1::、FF01:A123::都是本地接口广播地址。
9、isMCOrgLocal方法
当IP地址是组织范围的广播地址时返回ture,否则返回false。
使用组织范围广播地址可以向公司或企业内部的所有的计算机发送广播信息。IPv4的组织范围广播地址的第一个字节是239,第二个字节不小于192,第三个字节不大于195,如239.193.100.200、239.192.195.0都是组织范围广播地址。IPv6的组织范围广播地址的第一个字节是FF,第二个字节的范围是08 ~ F8,其他的字节可以是任意值,如FF08::、FF48::都是组织范围的广播地址。
10、isMCSiteLocal方法
当IP地址是站点范围的广播地址时返回true,否则返回false。使用站点范围的广播地址,可以向站点范围内的计算机发送广播信息。IPv4的站点范围广播地址的范围是239.255.0.0 ~ 239.255.255.255,如239.255.1.1、239.255.0.0都是站点范围的广播地址。IPv6的站点范围广播地址的第一个字节是FF,第二个字节的范围是05 ~ F5,其他的字节可以是任意值,如FF05::、FF45::都是站点范围的广播地址。
- /**
- * 判断该ip是否属于特殊IP
- * @param ip
- * @throws UnknownHostException
- * @throws IllegalAccessException
- * @throws IllegalArgumentException
- * @throws InvocationTargetException
- */
- public static void isTSIP(String ip) throws UnknownHostException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
- InetAddress address = InetAddress.getByName(ip);
- Method methods[] = InetAddress.class.getMethods();
- for (Method method : methods){
- if (method.getName().matches("is.*") && method.getParameterTypes().length == 0){
- if (Boolean.parseBoolean(method.invoke(address).toString())) {
- System.out.println("匹配:"+method.getName() + " = true");
- }else {
- System.out.println("查出:"+method.getName() + " = false");
- }
- }
- }
- }
五、DNS缓存
当InetAddress类第一次使用某个域名创建InetAddress对象后,JVM就会将这个域名和它从DNS上获得的信息(如IP地址)都保存在DNS缓存中。 当下一次InetAddress类再使用这个域名时,就直接从DNS缓存里获得所需的信息,而无需再访问DNS服务器。
DNS缓存在默认(-1)时将永远保留曾经访问过的域名信息,但我们可以修改这个默认值,两种方法:
1. 在程序中通过java.security.Security.setProperty方法设置安全属性networkaddress.cache.ttl的值(单位:秒)。
如下面的代码将缓存超时设为10秒:java.security.Security.setProperty("networkaddress.cache.ttl", 10); *
2. 设置java.security文件中的networkaddress.cache.negative.ttl属性。假设JDK的安装目录是C:\jdk1.6,那么java.security文件位于c:\jdk1.6\jre\lib\security目录中。打开这个文件,找到networkaddress.cache.ttl属性,并将这个属性值设为相应的缓存超时(单位:秒)。
- /**
- * DNS缓存在默认(-1)时将永远保留曾经访问过的域名信息,但我们可以修改这个默认值
- * 设置DNS缓存可以用java.security.Security.setProperty
- * 当InetAddress类第一次使用某个域名创建InetAddress对象后,JVM就会将这个域名和它从DNS上获得的信息(如IP地址)都保存在DNS缓存中。
- * 当下一次InetAddress类再使用这个域名时,就直接从DNS缓存里获得所需的信息,而无需再访问DNS服务器。
- * 1. 在程序中通过java.security.Security.setProperty方法设置安全属性networkaddress.cache.ttl的值(单位:秒)。
- * 如下面的代码将缓存超时设为10秒:java.security.Security.setProperty("networkaddress.cache.ttl", 10);
- * 2. 设置java.security文件中的networkaddress.cache.negative.ttl属性。假设JDK的安装目录是C:\jdk1.6,那么java.security文件位于c:\jdk1.6\jre\lib\security目录中。打开这个文件,找到networkaddress.cache.ttl属性,并将这个属性值设为相应的缓存超时(单位:秒)。
- * @param host 主机地址
- * @param timeout 缓存超时
- * @throws Exception
- */
- public static void setDNSCacheTime(String host,String timeout) throws Exception {
- java.security.Security.setProperty("networkaddress.cache.ttl", timeout);
- long time = System.currentTimeMillis();
- InetAddress addresses1[] = InetAddress.getAllByName(host);
- System.out.println("addresses1: "+ String.valueOf(System.currentTimeMillis() - time)+ "毫秒");
- for (InetAddress address : addresses1)
- System.out.println(address);
- System.out.print("按任意键继续");
- System.in.read();
- time = System.currentTimeMillis();
- InetAddress addresses2[] = InetAddress.getAllByName(host);
- System.out.println("addresses2: " + String.valueOf(System.currentTimeMillis() - time)+ "毫秒");
- for (InetAddress address : addresses2)
- System.out.println(address);
- }
在使用DNS缓存时有两点需要注意:
1. 可以根据实际情况来设置networkaddress.cache.ttl属性的值。一般将这个属性的值设为-1。但如果访问的是动态映射的域名(如使用动态域名服务将域名映射成ADSL的动态IP), 就可能产生IP地址变化后,客户端得到的还是原来的IP地址的情况。
2. 在设置networkaddress.cache.negative.ttl属性值时最好不要将它设为-1,否则如果一个域名因为暂时的故障而无法访问,那么程序再次访问这个域名时,即使这个域名恢复正常,程序也无法再访问这个域名了。除非重新运行程序。
六、判断一个ip是IPv4还是Ipv6
- /**
- * 判断这个IP地址是IPv4还是IPv6地址
- * @param host 主机地址
- * @return byte数组长度为4就是IPv4地址,byte数组长度为16就是IPv6地址
- * @throws UnknownHostException
- */
- public static int isInet4OrInet6(String host) throws UnknownHostException {
- InetAddress address = InetAddress.getByName(host);
- if(address instanceof Inet4Address) {
- return 4;
- }else if(address instanceof Inet6Address) {
- return 16;
- }else {
- return InetAddress.getByName(host).getAddress().length;
- }
- }
END
计划再运营一个微信公众号,欢迎大家莅临指导并留言:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。