Java网络编程net-1-地址-2

简介: Java网络编程net-1-地址-2

根据上篇文章的学习,大致看了看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地址的对象(这也属于第四个)

image.gif

通过以上方法,可以直接创建地址对象。

二、getHostName方法和getCanonicalHostName方法

getCanonicalHostName方法和getHostName方法一样,也是得到远程主机的域名。但它们有一个区别,getCanonicalHostName得到的是主机名,而getHostName得到的主机别名。

    • 使用getLocalHost创建InetAddress对象,getCanonicalHostName方法和getHostName方法得到的都是本机名。
    • 使用域名创建InetAddress对象,getCanonicalHostName方法是否要访问DNS服务器,取决于DNS服务器如何解释主机名和主机别名。也就是说,是否在创建InetAddress对象时就将主机名和主机别名都确定了。使用域名创建InetAddress对象后,调用getHostName方法不会访问DNS服务器。但getCanonicalHostName方法就不一定了。这和DNS服务器的设置有关。如www.126.com就需要访问DNS服务器,而www.ibm.com就不需要访问DNS服务器。
    • 使用IP地址创建InetAddress对象,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");
            }
          }
        }
      }

    image.gif

    五、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);
      }

    image.gif

    在使用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;
        }
      }

    image.gif

    END

    相关实践学习
    基于函数计算快速搭建Hexo博客系统
    本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
    目录
    相关文章
    |
    18天前
    |
    机器学习/深度学习 存储 计算机视觉
    r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现-4
    r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现
    |
    1天前
    |
    网络协议 算法 Java
    【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
    【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
    13 3
    |
    2天前
    |
    网络协议 Dubbo Java
    【网络编程】理解客户端和服务器并使用Java提供的api实现回显服务器
    【网络编程】理解客户端和服务器并使用Java提供的api实现回显服务器
    8 0
    |
    11天前
    |
    安全 Java 网络安全
    深入理解Java异常处理网络安全与信息安全:保护数据的关键策略
    【4月更文挑战第29天】本文将深入探讨Java中的异常处理机制,包括异常的概念、分类、捕获和处理等方面。通过详细的解析和实例演示,帮助读者更好地理解Java异常处理的原理和应用。 【4月更文挑战第29天】在数字化时代,数据成为最宝贵的资产之一。随着网络攻击的日益猖獗,了解并实施有效的网络安全和信息保护措施变得至关重要。本文将深入探讨网络安全漏洞的概念、加密技术的重要性以及提升个人和企业的安全意识的必要性。我们将分析当前的安全挑战,并提供一系列实用的防护策略,旨在帮助读者构建一个更加安全的数字环境。
    |
    14天前
    |
    网络协议 Java 网络架构
    Java基础教程(18)-Java中的网络编程
    【4月更文挑战第18天】Java网络编程简化了底层协议处理,利用Java标准库接口进行TCP/IP通信。TCP协议提供可靠传输,常用于HTTP、SMTP等协议;UDP协议则更高效但不保证可靠性。在TCP编程中,ServerSocket用于监听客户端连接,Socket实现双进程间通信。UDP编程中,DatagramSocket处理无连接的数据报文。HTTP编程可以通过HttpURLConnection发送请求并接收响应。
    |
    14天前
    |
    机器学习/深度学习 存储 算法
    r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现(下)
    r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现
    |
    18天前
    |
    机器学习/深度学习 算法 数据可视化
    r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现-3
    r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现
    |
    18天前
    |
    算法 数据可视化
    r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现-1
    r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现
    |
    21天前
    |
    监控 网络协议 Java
    《Java 简易速速上手小册》第7章:Java 网络编程(2024 最新版)
    《Java 简易速速上手小册》第7章:Java 网络编程(2024 最新版)
    23 0
    《Java 简易速速上手小册》第7章:Java 网络编程(2024 最新版)
    |
    网络协议 Java API