连接到Internet的设备称为节点node,其中计算机节点称为主机host
服务器至少有一个主机名,客户端往往有一个主机名,也可能没有,例如使用动态IP的主机,这里的主机名指的是DNS下的域名
服务器等往往会有多个主机名,并且一个主机名可以映射到多个IP,这种情况下DNS会随机选择一个响应请求,例如做负载均衡的服务器
InetAddress类
该类是Java对IP的高级表示,它主要包含主机名和IP地址,该类不提供set方式,即InetAddress是线程安全的。
InetAddress类没有公共的构造器,他通过静态工厂方法连接DNS完成解析,InetAddress中实现了缓存机制,已缓存的主机可以不连接DNS完成解析,如果DNS找不到该地址,则抛出UnknowHostException,他是IOException的子类
InetAddress类的getByName(),既可以使用域名获取地址,也可以通过地址反向查询域名,getByAddress可以创建地址,该方式在DNS不可用或者地址可能错的情况下很有用,该方法不保证该映射的合法性,只有当IP不合法是才会抛出UnknowHostException
package ch4;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class OReillyByName {
public static void main(String[] args) {
try {
InetAddress address = InetAddress.getByName("www.taobao.com");
System.out.println(address);
System.out.println("------------------------------");
//反向查询
InetAddress address2 = InetAddress.getByName("58.205.221.253");
System.out.println(address2.getHostName());
System.out.println("------------------------------");
//获取所有IP
InetAddress[] address3 = InetAddress.getAllByName("www.taobao.com");
for(InetAddress ad : address3) {
System.out.println(ad);
}
System.out.println("------------------------------");
//获取本机地址,失败则返回回环地址
InetAddress address4 = InetAddress.getLocalHost();
System.out.println(address4);
//根据IP创建地址,尤其适用于DNS不可用或者地址可能不正确的情况
System.out.println("------------------------------");
// 大数字必须转换byte,Java的byte是有符号数
byte[] address5 = {107, 23, (byte)216, (byte)196};
InetAddress lessWrong = InetAddress.getByAddress(address5);
InetAddress lessWrongWithName = InetAddress.getByAddress("lessWrong.com", address5);
System.out.println(lessWrong);
System.out.println(lessWrongWithName);
} catch(UnknownHostException e) {
System.err.println(e);
}
}
}
InetAddress缓存
InetAddress会对DNS解析结果进行缓存,一旦得到一个给定主机的地址,就不会再查找,即使为同一个主机创建了新的InetAddress对象
对于查询不成功的对象,缓存保存时间是10s
通过networkaddress.cache.tt;设置成功查询的Java缓存保存时间,networkaddress.cache.native.ttl指定查询不成功的Java缓存保存时间
按IP地址查询
在可以选择的情况下,优先选择按主机名查询,而不是按IP,因为对于getByName()方法如果按照IP查询,会为每个请求的IP创建一个InetAddress对象,而不检查DNS,请主机名就是该点分四段字符串,只有当显示调用getHostName()时才会正真完成DNS的查找,这就存在为无法连接的主机创建了InetAddress,而查询失败则设置点分四段字符串为主机名,不是抛出UnkonwnHostException!!!
安全性
通过主机名创建新的InetAddress对象被认为是不安全的