概念

IP地址对应在Java中的类是InetAddress类,在了解InetAddress之前先介绍几个概念

  • 节点(node)
    连接到网络的设备叫节点
  • 主机(host)
    如果节点是计算机则叫主机
  • IP地址
    网络中区分节点的唯一数字叫IP地址

InetAddress类

InetAddress是Ipv4地址和Ipv6地址的父类,它同时包含了hostname和IP地址

创建InetAddress对象

它没有公共的构造函数,但是有一个静态工厂方法,这个方法通过连接DNS服务器来解析hostname。
​​​InetAddress address = InetAddress.getByName("www.skybility.com");​

下面给出完整的例子

@Test
public void testGetByName() throws UnknownHostException {
InetAddress address = InetAddress.getByName("www.baidu.com");
System.out.println(address);//www.baidu.com/14.215.177.38

也可以通过IP地址来查询hostname:

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

不过这个方法不太好使,大多数情况会返回你传入的IP地址。同时,这个方法比getByAddress更加便捷,因为可以传入IP地址的字符串形式。

如果某个域名配置了多个IP地址,可以通过下面的方法得到这些IP地址:

public void testGetAllByName() throws UnknownHostException {
try {
InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");
for (InetAddress address : addresses) {
System.out.println(address);
}
} catch (UnknownHostException ex) {
System.out.println(ex.getMessage());
}
}

输出:

www.baidu.com/14.215.177.39
www.baidu.com/14.215.177.38

如果想知道本机地址,可通过getLocalHost来返回

@Test
public void testGetLocalHost() throws UnknownHostException {
InetAddress address = InetAddress.getLocalHost();
System.out.println(address);//USERCHI-UA6LONB/192.168.5.42

如果你知道数值形式的IP地址,那么就可以通过调用getByAddress来创建对象,通常用来创建hostname无法解析或主机不存在的IP地址。

以下是方法签名:

public static InetAddress getByAddress(byte[] addr) throws UnknownHostException
public static InetAddress getByAddress(String hostname, byte[] addr) throws
public void testGetByAddress() throws UnknownHostException {
byte[] address = {14,(byte) 215,(byte)177,39};//byte最大值127
InetAddress lessWrong = InetAddress.getByAddress(address);
System.out.println(lessWrong);// /14.215.177.39
InetAddress lessWrongWithname = InetAddress.getByAddress(
"baidu.com", address);
System.out.println(lessWrongWithname); // baidu.com/14.215.177.39

这个方法不保证hostname和ip地址的关联的正确性,也就是hostname可以任意输入。

InetAddress一旦构造好之后是无法修改的,这样可以使它是线程安全的

Address类型

IP地址常见的类型有,127.0.0.1是本地回环地址(local loopback address);224.0.0.0~239.255.255.255是多播地址(multicast address)。

Java提供了10个方法来检测地址类型:

/**
* 返回是否为一个通配符地址(wildcard address:0.0.0.0)
*/
public boolean isAnyLocalAddress()
//返回是否为回环地址
public boolean isLoopbackAddress()
//返回是否为IPV6本地链路地址 前缀FE80::/10
public boolean isLinkLocalAddress()

public boolean isSiteLocalAddress()
/**
*返回是否是多播地址
*/
public boolean isMulticastAddress()
//返回是否为全球多播地址 以FFOE或FF1E开头
public boolean isMCGlobal()

用作服务端,0.0.0.0可表示本机上的任意IPV4地址

0.0.0.0和127.0.0.1的区别?
127.0.0.1 是一个环回地址。并不表示“本机”。0.0.0.0才是真正表示“本网络中的本机”。
在实际应用中,一般我们在服务端绑定端口的时候可以选择绑定到0.0.0.0,这样我的服务访问方就可以通过我的多个ip地址访问我的服务。
比如我有一台服务器,一个外放地址A,一个内网地址B,如果我绑定的端口指定了0.0.0.0,那么通过内网地址或外网地址都可以访问我的应用。但是如果我只绑定了内网地址,那么通过外网地址就不能访问。 所以如果绑定0.0.0.0,也有一定安全隐患,对于只需要内网访问的服务,可以只绑定内网地址。

站点本地地址(SiteLocalAddress)与链路本地地址类似,站点本地地址可被路由器在站点或校园内传播,但无法传播到站点或校园之外。以FEC0:0:0:0开头。

Inet4Address和Inet6Address

它们都继承了InetAddress,分别表示IPv4地址和Ipv6地址。通过检查getAddress()方法返回的字节数组大小可以比​​instance of​​ 更快的检查InetAddress的具体类型。

NetworkInterface类

它代表了网卡,既可以是物理网卡也可以是虚拟网卡。

工厂方法

该类无法被任意的构造,可通过IP地址,名称或枚举得到该类的实例。

getByName

try {
NetworkInterface ni = NetworkInterface.getByName("eth0");
if (ni == null) {
System.err.println("No such interface: eth0");
}else{
System.out.println(ni);//name:eth0 (VirtualBox Host-Only Ethernet Adapter)
}

} catch (SocketException ex) {
System.err.println("Could not list sockets.");
}

getByInetAddress

.getLocalHost();
NetworkInterface ni = NetworkInterface.getByInetAddress(address);
System.out.println(ni);//name:eth7 (Intel(R) Ethernet Connection (2) I219-V)

getNetworkInterfaces返回本机所有的网卡:

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

输出:

name:lo (Software Loopback Interface 1)
name:eth0 (VirtualBox Host-Only Ethernet Adapter)
name:eth1 (VMware Virtual Ethernet Adapter for VMnet8)
name:net0 (Microsoft ISATAP Adapter)
name:net1 (Teredo Tunneling Pseudo-Interface)
name:eth2 (VMware Virtual Ethernet Adapter for VMnet1)
name:net2 (WAN Miniport (L2TP))
...

Get方法

一旦你有一个网卡对象,你就可以通过​​getInetAddresses()​​得到绑定在该网卡上的IP地址。

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