InetAddress代表一个IP地址。很多其他网络类都需要用到这个类。例如Socket、ServerSocket、URL等。

构造InetAddress

InetAddress这个类并没有公用的构造方法,我们不能通过构造方法来创建InetAddress对象,但是它提供了一些静态工厂方法,我们可以使用这些工厂方法来构建对象。这里我们来看一个常用的方法:

  1. public static InetAddress getByName(String host)
  2. throws UnknownHostException {
  3. return InetAddress.getAllByName(host)[0];
  4. }

通过给定一个host来获取InetAddress对象,这个host可以是一个域名,例如www.baidu.com,也可以是一个ip,例如192.168.121.221。它是通过调用另外一个getAllByName方法实现的,我们先不去看这个方法,来写几个例子:

  1. public static void main(String[] args) throws IOException {
  2. InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
  3. System.out.println(inetAddress.getHostAddress());
  4. InetAddress localHost = InetAddress.getLocalHost();
  5. System.out.println(localHost.getHostName());
  6. System.out.println(localHost.getHostAddress());
  7. }

第一个是获取www.baidu.com这个域名的地址,注意一个域名可能对应多个主机也就是多个ip地址,这里获取的只是这些地址中的一个。getLocalHost是获取本机的地址,我们看输出:

  1. 110.242.68.4
  2. cuihualongdeMacBook-Pro.local
  3. 192.168.20.89

也就是www.baidu.com的机器ip是110.242.68.4,我机器的ip是192.168.20.89,我机器的主机名是cuihualongdeMacBook-Pro.local。inetAddress的getHostName返回的是主机名,getHostAddress返回的是机器ip。
因为一个域名可能对应多个ip,所以正常情况下对于一个host,应该返回的是一个InetAddress的数组,这就是上面我们看到的getAllByName方法的功能,getByName也是获取的getAllByName返回的数组的第一个。我们来用一下getAllByName这个方法:

  1. public static void main(String[] args) throws IOException {
  2. InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");
  3. for (InetAddress address : allByName) {
  4. System.out.println(address.getHostAddress());
  5. }
  6. }

输出:

  1. 110.242.68.3
  2. 110.242.68.4

所以www.baidu.com应该是有两台机器。
然后我们来看geAllByName的逻辑:

  1. public static InetAddress[] getAllByName(String host)
  2. throws UnknownHostException {
  3. return getAllByName(host, null);
  4. }

它调用的是getAllByName(),这里的逻辑有点多,就不再解释了。

可达性判断

InetAddress还提供了方法来判断这个地址的可达性:

  1. public boolean isReachable(int timeout) throws IOException {
  2. return isReachable(null, 0 , timeout);
  3. }

它调用的是另外一个isReacheable方法:

  1. public boolean isReachable(NetworkInterface netif, int ttl,
  2. int timeout) throws IOException {
  3. if (ttl < 0)
  4. throw new IllegalArgumentException("ttl can't be negative");
  5. if (timeout < 0)
  6. throw new IllegalArgumentException("timeout can't be negative");
  7. return impl.isReachable(this, timeout, netif, ttl);
  8. }

我们不去看代码逻辑,从注释看一下它是怎样判断可达性的:

  1. Test whether that address is reachable. Best effort is made by the
  2. * implementation to try to reach the host, but firewalls and server
  3. * configuration may block requests resulting in a unreachable status
  4. * while some specific ports may be accessible.
  5. * A typical implementation will use ICMP ECHO REQUESTs if the
  6. * privilege can be obtained, otherwise it will try to establish
  7. * a TCP connection on port 7 (Echo) of the destination host.

如果有权限的话,它会使用ICMP ECHO REQUEST来判断可达性,否则会尝试建立一个到目的主机的7端口号的TCP连接。