Java 网络编程 -- IP地址

InetAddress类

  1. java.net.InetAddress类是Java对IP地址的高层表示。
  2. 包括IPv4和IPv6的表示。
  3. 一般来说,包括一个“主机名”和一个“IP地址”。
  4. 大多数其他网络类都要使用到这个类,包括Socket、ServerSocket、URL、DatagramSocket、DatagramPacket等。

静态工厂方法

  • getByName(String url)
  • getLocalHost()
  • getByAddress()
  • getAllByName()

getByName(String url)方法

InetAddress.getByName("www.xxx.com")
  1. 会建立与本地DNS服务器的一个连接。
  2. 如果之前查找过这个主机,信息可能在本地缓存,这时不需要建立网络连接。
  3. 如果DNS服务器找不到这个地址,会抛出UnknownHostException,是IOException的一个子类。
  4. 可以按IP地址反向查找,如果查找的地址没有相应的主机名,getHostName()就会返回提供的点分地址。
  5. 参数为IP地址时,不检查DNS,在调用getHostName()时,才会检查DNS。

示例:

try {
  InetAddress address = InetAddress.getByName(www.xxx.com);
  System.out.println(address);
} catch (UnknownHostException ex) {
  System.out.println("Counld not find www.xxx.com");
}

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

getLocalHost()方法

  1. getLocalHost()会为运行这个代码的主机返回一个InetAddress对象。
  2. 这个方法尝试连接DNS来得到一个真正的主机名和IP地址。如果失败,就会返回“会送地址”,即主机名localhost和点分四段地址127.0.0.1

示例:

try {
  InetAddress address = InetAddress.getLocalHost();
  System.out.println(address);
} catch (UnknownHostException ex) {
  System.out.println("Could not find this computer's address.")
}

getByAddress()方法

getByAddress()方法,不与DNS交互。可以为不存在或无法解析的主机创建地址。

方法原型:

public static InetAddress getByAddress(byte[] addr) throws UnKnownHostException
public static InetAddress getByAddress(String hostname, byte[] addr) throws UnknownHostExeption

示例:

byte[] address = {107, 23, (byte)216, (byte)196};
InetAddress lessWrong = InetAddress.getByAddress(address);
InetAddress lessWrongWithName = InetAddress.getByAddress("lesswrong.com", address);
  1. 需要把地址中的大数字转换为字节。
  2. 这两个方法不能保证这个主机一定存在,或者主机名能正确地映射到IP地址。
  3. 只有当作为address的参数传入的字节数组大小不合法时(不是4字节,也不是16字节),这两个方法才会抛出UnknownHostException

getAllByName()方法

  1. 如果www.xxx.com实际有多个地址,getHostName()返回哪一个地址是不确定的。
  2. 可以调用getAllByName()会返回一个InetAddress数组。

示例:

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

获取方法

  1. InetAddress有几个获取方法:
  • public String getHostName()
  • public String getCanonicalHostName()
  • public byte[] getAddress()
  • public String getHostAddress()
  1. 没有对应的setHostName()setAddress()方法,这说明java.net之外的包无法在后台改变InetAddress对象的字段。这使得InetAddress不可变,因此是“线程安全”的。

getHostName()方法

  1. 返回一个String,包含主机名,和IP地址。
  2. 如果没有主机名,或者安全管理器组织确定主机名,就会返回点分四段式的数字IP地址。

getCanonicalName()方法

  1. getHostName()只是在不知道主机名时,才会联系DNS。
  2. getCanonicalHostName()知道主机名时,也会联系DNS,可能会替换原来缓存的主机名。

getAddress() 方法

  1. 获取IP地址,会以网络字节顺序将IP地址作为字节数组返回。
  2. Java没有“无符号字节”这种基本数据类型。值大于127的字节会当做负数。因此需要做一些调整。
  3. 通过判断返回字节数组的元素个数,来确定是IPv4还是IPv6。
int unsignedByte = signedByte < 0 ? signedByte + 256 : signedByte;

地址类型

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()

测试可达性

  1. InetAddress类有两个isReachable()方法。
  2. 可以测试一个特定节点对当前主机是否可达(能否建立一个网络连接)。
方法原型
public boolean isReachable(int timeout) throws IOException
public boolean isReachable(NetworkInterface, int ttl, int timeout) throws IOException
  1. 这些方法使用traceroute(更确切的讲,是ICMP echo请求)查看指定地址是否可达。
  2. 如果主机在timeout毫秒内响应,则方法返回true;否则返回false。如果出现网络错误,则抛出IOException异常。
  3. 第二个方法还允许制定从哪个“本地网络接口”建立连接,以及“生存时间”。

Object方法

  1. equals()hashCode()方法,只根据IP地址,和主机名无关。
  2. toString()方法,打印主机名/IP地址

Inet4Address和Inet6Address

public final class Inet4Address extends InetAddress
public final class Inet6Address extends InetAddress
  1. 这两个类专门用于IPv4和IPv6。
  2. Inet6Address增加了一个isIPv4CompatibleAddress()

缓存

  1. 由于DNS查找的开销可能很大,所以InetAddress类会缓存查找的结果。
  2. 一旦得到一个给定主机的地址,就不会再次查找,即使为统一主机创建一个新的InetAddress对象,也不会再次查找地址。
  3. Java对于不成功的DNS查询只缓存10秒。
  4. 缓存时间,可以用系统属性networkaddress.cache.ttlnetworkaddress.cache.negative.ttl来控制。-1表示“永不过期”。
  5. 除了在InetAddress类中的本地缓存,本地主机、本地域名服务器、Internet上其他地方的DNS服务器也会缓存各种查询的结果。对此,Java没有提供相关控制方法。

NetworkInterface类

  1. NetworkInterface类表示一个“本地IP地址”。
  2. 可以是一个“物理接口”,也可以是一个“虚拟接口”。

工厂方法

public static NetworkInterface getByName(String name) throws Socketexception
public static NetworkInterface getByInetAddress(InetAddress address) throws SocketException
public static Enumeration getNetworkInterfaces() throws SochetException

getByName()方法

  1. 返回一个NetworkInterface对象,表示有指定名字的网络接口。
  2. 如果没有这样一个接口,就返回null
  3. 如果在查找相关网络接口时,底层网络栈遇到问题,会抛出一个SocketException异常。
  4. 名字的格式与平台有关。
  5. UNIX系统上,以太网接口的形式为eth0eth1等。本地回送地址的名字可能类似lo
  6. Windows上,名字类似CE31ELX100等。
try {
  NetworkInterface ni = NetworkInterface.getByName("eth0");
  if (ni = null) {
    System.out.println("No such interface: eth0");
  }
} catch (SocketException ex) {
  System.out.println("Could not list sockets.");
}

getByInetAddress()方法

getByName()类似。

// ...
InetAddress local = InetAddress.getByName("127.0.0.1");
NetworkInterface ni = NetworkInterface.getByInetAddress(local);
// ...

getNetworkInterfaces()方法

返回本地主机上的所有网络接口.

Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
  NetworkInterface ni = interfaces.nextElement();
  System.out.println(ni);
}

获取方法

public Enumeration getInetAddresses()
public String getName()
public String getDisplayName()

有了NetworkInterface对象,就可以查询其IP地址和名字。

getInetAddresses()方法

一个网络接口可以绑定多个IP地址,这个方法返回绑定的所有IP地址。

NetworkInterface eth0 = NetworkInterface.getByName("eth0");
Enumeration addresses = rth0.getInetAddresses();
while (addresses.hasMoreElements()) {
  System.out.println(addresses.nextElement());
}

getDisplayName()

声称可以返回更好的名字。

你可能感兴趣的:(Java 网络编程 -- IP地址)