c4 Internet Addresses - The InetAddress Class

每台连接到Internet的电脑都要能访问一台叫domain name server的机器(DNS服务器),一般是运行在Unix上的DNS软件,知道不同hostnames和ip address对应关系。大部分dns只知道本地网络的域名和ip地址和一些其他dns服务器地址,当client请求解析域名时,如果在本地没有mapping,那本地dns就向其他dns发送请求,然后转发给请求者。


Creating New InetAddress Objects


类 java.net.InetAddress 是java中代表IP Address的最高level的类。

InetAddress address = InetAddress.getByName("www.oreilly.com");

该方法会连接本地DNS,寻找hostname和ip address,如果之前已访问过该hostname,那在本地会有缓存,就不会联网了。

也可以通过ip address 创建一个InetAddress 

InetAddress address = InetAddress.getByName("208.201.239.100");
System.out.println(address.getHostName());

如果没有对应的hostname,getHostName()会返回刚才的ip address。

当一个域名对应多个ip address 时,

try {
  InetAddress[] addresses = InetAddress.getAllByName("www.oreilly.com");
  for (InetAddress address : addresses) {
    System.out.println(address);
  }
} catch (UnknownHostException ex) {
  System.out.println("Could not find www.oreilly.com");
}

当要获取本机的hostname和ip address时,

InetAddress me = InetAddress.getLocalHost();

会连接本地DNS服务器获取本机hostname和ip address,如果失败,则返回本地回环地址 127.0.0.1。


byte[] address = {107, 23, (byte) 216, (byte) 196};
InetAddress lessWrong = InetAddress.getByAddress(address);
InetAddress lessWrongWithname = InetAddress.getByAddress(
   "lesswrong.com", address);

这2个方法不保证host存在或者有hostname对应那个ip 地址,只在address 的 byte array参数大小不正确时(既不是4个字节,也不是16个字节)抛出UnknownHostException异常。在hostname不存在或不准确时,这些方法会用得着。


Caching

因为DNS lookup开销比较大,要解析一个域名可能要在多个DNS服务器间查询,并且可能最终没有匹配的ip地址,所以,InetAddress会缓存域名-ip地址,只要程序运行的ip地址没有改变,即使新创建了InetAddress,也会使用缓存。


对于否定的结果(比如host not found)比较麻烦,很可能第一次解析的时候,由于timeout而返回失败信息,但紧接着从remote dns就返回了结果,那下一次请求就会有解析的结果,所以,java对Negative result只保存10s。


通过更改系统的networkaddress.cache.ttl 可以更改successful保存的时间,更改 networkaddress.cache.negative.ttl可以修改negative result保存时间。在limited时间内,lookup同样的host会返回保存的结果,-1的意思是永不过期!


除了InetAddress,本地host,本地dns,还有其他dns都会缓存解析结果,对后面的缓存,java没有办法控制!ip地址变化的信息要在整个internet上被各个dns都知道,可能要花去好多小时,在此期间,访问该域名会报出各种异常,比如NoRouteToHostException,UnknownHostException,ConnectException,具体什么异常要看对DNS作了什么改动。


Looksup By Name

通过getByName(),将ip地址作参数传进去,会创建InetAddress对象,但不会连接DNS,不保证hostname一定存在或者可以访问,只在需要hostname时或者显式调用getHostName时才连DNS,如果没有hostname,那hostname就会是传入的参数,不会报UnknownHostException!


Security issue

通过hostname创建的InetAddress是安全的,因为要通过DNS查找ip地址。通过ip地址获得的InetAddress是不安全的,因为不走DNS,这些代码被称为untreated code。

untreated code不允许进行任意DNS查询。程序可以通过任意的DNS查询和第三方DNS通话。任意DNS查询会泄露信息。

检测一个host或者host上的port能否被resolved,可以用SecurityManager的方法checkConnect(hostname,port)

public void checkConnect(String hostname, int port)
这个方法又没有返回值,怎么知道可否resolved呢?


Getter Methods

public String getHostName()
public String getCanonicalHostName()
public byte[] getAddress()
public String getHostAddress()

注意没有setHostName(),setHostAddress()方法,这意味着在包java.net以外无法修改InetAddress的field值,说明InetAddress是immutable,thread safe。


getHostName()返回String,hostname,如果hostname取不到,或者security manager阻止获取hostname,则返回ip地址。


getCanonicalHostName()与getHostName()类似,区别在getHostName只在不知道hostname时,才连接DNS服务器获取hostname,而getCanonicalHostName()只要能连接DNS就会去连接,并在取到hostname后会替换现有的。


getHostAddress() 返回ip 地址。


getAddress()返回字节数组,java没有提供unsigned基本数据类型,对一个byte来说,大于127的就是负数了,所以,要把getAddress返回的byte array转换成正确的int。

int unsignedByte = signedByte < 0 ? signedByte + 256 : signedByte;

getAddress()的一个目的是可以查看ip地址类型

    byte[] address = ia.getAddress();
    if (address.length == 4) return 4;
    else if (address.length == 16) return 6;
    else return -1;


Address Types

java提供了10种方法检测一个InetAddress是哪种类型的地址

public boolean isAnyLocalAddress()
public boolean isLoopbackAddress()
public boolean isLinkLocalAddress()
public boolean isSiteLocalAddress()
public boolean isMulticastAddress()
public boolean isMCGlobal()
public boolean isMCNodeLocal()
public boolean isMCLinkLocal()
public boolean isMCSiteLocal()
public boolean isMCOrgLocal()

Testing Reachability

public boolean isReachable(int timeout) throws IOException
public boolean isReachable(NetworkInterface interface, int ttl, int timeout)
    throws IOException

从当前note是否可以连接到某个特定的note。如果在timeout时间内,host有response,返回true,如果没有false。

第二个方法中可以设置建立连接的本地网络interface,time-to-live 在被丢弃前允许尝试连接的最多次数。


Object Methods

public boolean equals(Object o)
public int hashCode()
public String toString()

InetAddress重写了Object的上述3个方法

equals():当2个对象都是InetAddress,并且有相同的ip地址时,返回true,不必有相同的hostname。不同的     hostname可以指向相同的ip地址,指向同一台机器。

hashCode():用ip地址计算得来的hashcode值,只要ip地址相同,hashcode就相等,hostname不参与计算。

toString():返回 hostname/dotted quad address












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值