JAVA网络编程个人笔记 第4章 inet地址
Internet寻址
- java.net.InetAddress类是JAVA对IP地址(包括IPV4和IPV6)的高层表示。包括一个主机名和一个IP地址
- InetAddress描述了32位128位IP地址,是IP地址封装类
- InetAddress类主要依靠Inet4Address类和Inet6Address类
- 在java.net包中
创建InetAddress对象
InetAddress类没有构造函数,因此不能用new来构造一个InetAddress实例。而是采用静态方法,连接到DNS服务器来解析主机名
常用方法
- getLocalHost
- getByName和getAllByName
- getByAddress
这三个方法通常会产生UnknownHostException例外,应在程序中捕获处理
getLocalHost()
语法:
public static InetAddress getLocalHost()throws UnknownHostException
InetAddress me = InetAddress.getLocalHost();
会获取一个运行代码的主机的InetAddress对象。
如果没一个固定的IP地址和域名会看到localhost/127.0.0.1
代码实现
import java.net.InetAddress;
import java.net.UnknownHostException;
public class getLocalHostDemo {
public static void main(String[] args) {
try{
InetAddress me = InetAddress.getLocalHost();
System.out.print(me);
}catch(UnknownHostException e){
e.printStackTrace();
}
}
}
getByName()
语法:
public static InetAddress getByName(String host) throws UnknownHostException
InetAddress address = InetAddress.getByName("www.fafu.edu.cn");
这个方法会连接本地DNS服务器,来查找名字和数字地址(当然如果有缓存直接查缓存)。如果找不到这个地址会抛出一个异常
这个方法并不验证IP地址的正确性
代码实现
try{
String host = "localhost";
InetAddress address = InetAddress.getByName(host);
System.out.println(address);
}catch(UnknownHostException e){
e.printStackTrace();
}
try{
InetAddress address = InetAddress.getByName("www.baidu.com");
System.out.println(address);
}catch(UnknownHostException e){
e.printStackTrace();
}
getAllByName()
语法:
public static InetAddress[] getAllByName(String host) throws UnknownHostException
getAllByName()通过从DNS中得到域名响应的所有IP地址
这个方法并不验证IP地址的正确性
代码实例
import java.io.IOException;
import java.net.InetAddress;
public class getAllByNameDemo {
public static void main(String[] args) throws IOException{
InetAddress addr = InetAddress.getLocalHost();
System.out.println("local host:"+addr);
addr = InetAddress.getByName("google.com");
System.out.println("google:"+addr);
InetAddress[] addrs = InetAddress.getAllByName("www.baidu.com");
for(int i = 0;i < addrs.length;i++)
System.out.println("baidu:"+addrs[i]+" number:"+i);
System.out.println(InetAddress.getByName("localhost").isReachable(1000));
}
}
getByAddress()
语法:
public static InetAddress getByAddress(byte[] addr) throw UnknownHostException
public static InetAddress getByAddress(String hostname,byte[] addr)throw UnknownHostException
getByAddress()通过IP地址创建InetAddress对象,而且IP地址必须是byte数组形式
并不适用hostname在DNS上查找IP地址,这个hostname只是一个用于表示addr的别名,不同于上述几个方法中的host
如果知道一个数字地址,可以通过上述代码创建对象,需要注意的是:
- 大数字需要加byte转换,否则变成负数
- 另外这个方法并不保证主机一定存在或者主机名能映射到正确的IP地址
- 只有当address参数传入的字节数组大小不合法的时候才会抛出异常UnknownHostException
- 可以用来检测子网中有哪些IP可用‘
代码实现
import java.net.*;
public class getByAddressDemo {
public static void main(String[] args) {
try{
byte ip[] = new byte[]{(byte) 141,(byte) 146,8,66};
InetAddress address1 = InetAddress.getByAddress(ip);
InetAddress address2 = InetAddress.getByAddress("Oracle官方网站",ip);
System.out.println(address1);
System.out.println(address2);
}catch(UnknownHostException e){
e.printStackTrace();
}
}
}
根据域名查找IP
根据域名查找IP地址,返回的IP地址可能是ipv4的地址,也可能是IPv6的地址,这种方式访问DNS服务器
- public String getHostAddress():获得对象的IP地址
- public byte[] getAddress():获得本对象的IP地址(存放在字节数组中)
getHostAddress()代码实现
import java.net.*;
public class getHostAddress {
public static void main(String[] args) {
try{
String host = "www.baidu.com";
InetAddress address = InetAddress.getByName(host);
System.out.println("Host address ="+address.getHostAddress());
}catch(UnknownHostException e){
e.printStackTrace();
}
}
}
IP地址分类
IP地址常用A、B、C三类,他们均由网络号和主机号两个部分组成,规定每一组都不能用全1和全0,通常全0表示网络本身地址,全1表示网络广播的IP地址。为了区分A、B、C,三类的最高位分别是0、10、110
代码实例
import java.net.*;
public class IPAddress {
public static void main(String[] args) {
try {
String host = "222.188.0.30";
InetAddress addr = InetAddress.getByName(host);
byte[] address = addr.getAddress();
if (address.length == 4) {
System.out.println("The IP version is IPv4");
int firstbyte = address[0];
if (firstbyte < 0) firstbyte += 256;
if ((firstbyte & 0x80) == 0) System.out.println("the ip class is A");
else if ((firstbyte & 0xC0) == 0x80) System.out.println("the ip class is B");
else if ((firstbyte & 0xE0) == 0xC0) System.out.println("the ip class is C");
else if ((firstbyte & 0xF0)== 0xE0) System.out.println("the ip class is E");
}
else if(address.length == 16)
System.out.println("the ip version is IPv6");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
getAddress()方法
- 定义: public byte[] getAddress()
- 该方法和getHostAddress方法唯一区别是:getHostAddress返回字符形式的IP地址,getAddress返回byte[]形式的IP地址
- byte数组是有符号的。在JAVA中byte类型的取值范围是-128~127
- 如果返回的IP地址的某个字节是大于127的整数,在byte数组中就是负数
- 由于JAVA中没有无符号byte类型,因此,要显示正常的IP地址,必须使用int或long类型
根据IP地址查找主机名
- public String getHostName() 根据创建InetAddress对象的不同方式,getHostName的返回值是不同的
- 如果通过域名创建InetAddress对象,返回值为主机名
- 如果通过IP地址创建InetAddress对象,返回值为IP地址
- 如果被查询的机器没有主机名,或者使用了applet,但是他的安全性却禁止查询主机名,返回值为IP地址
- public String getCanonicalHostName()该方法和getHostName()方法一样,也是得到远程主机的域名。区别是,该方法得到的是主机名,getHostName得到的是主机别名
代码实现
import java.net.*;
public class getHostNameDemo {
public static void main(String[] args) {
try {
String host = "www.baidu.com";
InetAddress address = InetAddress.getByName(host);
System.out.println(address.getHostName());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
toString()
语法:
- public String toString()
- 得到主机名和IP地址的字符串
代码实现
import java.net.InetAddress;
import java.net.UnknownHostException;
public class toStringDemo {
public static void main(String[] args) {
try{
String host ="www.baidu.com";
InetAddress address = InetAddress.getByName(host);
System.out.println(address.toString());
}catch(UnknownHostException e){
e.printStackTrace();
}
}
}
getCanonicalHostName()方法
- 使用getLocalHost创建InetAddress对象
- getCanonicalHostName方法与getHostName方法得到的都是本机名
- 使用域名创建InetAddress对象
- getCanonicalHostName方法是否要访问DNS服务器,取决于DNS服务器如何解释主机名和主机别名。使用域名创建InetAddress对象,调用getHostName不会访问DNS服务器
- 使用IP地址创建InetAddress对象
- getCanonicalHostName方法与getHostName方法得到 都是主机名。而不是主机别名
代码实现
import java.net.InetAddress;
public class getCanonicalHostNameDemo {
public static void outHostName(InetAddress address,String s){
System.out.println("通过"+s+"创建InetAddress对象");
System.out.println("主机名:"+address.getCanonicalHostName());
System.out.println("主机别名:"+address.getHostName());
System.out.println("");
}
public static void main(String[] args) throws Exception{
outHostName(InetAddress.getLocalHost(),"getLocalHost方法");
outHostName(InetAddress.getByName("www.ibm.com"),"www.ibm.com");
outHostName(InetAddress.getByName("www.126.com"),"www.126.com");
outHostName(InetAddress.getByName("202.108.9.77"),"202.108.9.77");
outHostName(InetAddress.getByName("211.100.26.121"),"211.100.26.121");
}
}
Inet4Address类和Inet6Address类
- Inet4Address类和Inet6Address类均是InetAddress类的子类
- Inet6Address类多了一个isIPv4CompatibleAddress方法
- 当使用InetAddress类的四个静态方法创建InetAddress对象后,可以通过getAddress返回的byte数组判断是IPv4还是IPv6.也可以使用instanceof来确定InetAddress对象是哪个子类的实例
语法:
public final Inet4Address extends InetAddress
public final Inet6Address extends InetAddress
可用getAddress()返回的数组长度判断IP地址类型
IPv6地址表示
- IPv6地址为128位长,但通常写作8组,每组为四个十六进制数的形式
- 可以使用零压缩法缩减其长度
判断IPv4地址与IPv6地址代码实例
import java.net.*;
public class IPv4IPv6Demo {
public static void main(String[] args) {
String host = "www.baidu.com";
try{
InetAddress address = InetAddress.getByName(host);
System.out.println("IP:"+address.getHostAddress());
switch (address.getAddress().length){
case 4:
System.out.println("根据byte数组长度判断这个IP地址为IPv4地址");
break;
case 16:
System.out.println("根据byte数组长度判断这个IP地址是IPv6地址");
break;
}
if(address instanceof Inet4Address)
System.out.println("使用instanceof判断这个IP地址是IPv4地址");
else if(address instanceof Inet6Address)
System.out.println("使用instanceof判断这个IP地址是IPv6地址");
}catch (UnknownHostException e){
e.printStackTrace();
}
}
}
NetworkInterface类
- 可以使用NetworkInterface类提供的方法获取本地计算机网络接口相关的信息
- 尽管InetAddress类提获取IP地址的方法,但是要想获取本机的网络接口的详细信息,还需要依赖NetworkInterface接口中的方法
- 通过NetworkInterface接口,可以获取本机配置的网络接口的名称,IP列表(包括IPv4和IPv6),网卡地址,最大传输单元(MTU),接口状态(开启/关闭)、接口网络类型(点对点网络、回环网络)等信息
- 上图列出来了NetworkInterface中可用的公有方法。可以看出,NetworkInterface没有可见的构造方法,NetworkInterface内部也是使用静态方法来构造NetworkInterface实例的(简单工厂方法)
- 此外每个NetworkInterface内部可以包含多个NetworkInterface对象,这就构成了一种树结构(合成模式),而且每个NetworkInterface内部保持了一个指向父NetworkInterface的引用
- NetworkInterface类和InetAddress引用,也没有public的构造方法。因此,必须通过他的静态方法来创建networkInterface对象
- 可以使用两种方法来创建networkInterface对象:网络接口名(getByName方法)和IP地址(getByInetAddress方法)
getByName方法
- 这个方法可以通过网络接口名来创建NetworkInterface对象。这个网络接口名并不是计算机名,而是用于表示物理或逻辑网络接口的名字,一般是由操作系统设置的。网络接口名在大多数操作系统上是以eth开头,后面是网络接口的索引号从0开始
- NetworkInterface对象的toString方法可以返回网络接口的名称、显示名和这个网络接口上绑字的所有IP地址等信息。当网络接口名不存在,getByName返回null
getByInetAddress方法
除了可以使用网络接口名来得到网络接口的信息,还可以利用getByInetAddress方法来确定一个IP地址属于哪一个网络接口。由于getByInetAddress方法必须使用一个InetAddress对象封装的IP地址来作为参数。因此,在使用getByInetAddress方法之前,必须先创建一个InetAddress对象。但要注意不能使用远程的IP的域名来创建InetAddress对象,否则getByInetAddress将返回null
两个方法的具体语法
- 表示物理网卡或虚拟网卡
- static NetworkInterface getByName(String name)
- 列出接口的所有IP
- static Enumeration getInetAddresses()
Enumeration接口中定意思了一些方法,通过这些方法可以枚举对象集合中的元素
- boolean hasMoreElements()测试此枚举是否包含更多的元素
- Object nextElement()如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素
代码展示
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
public class NetworkInterfaceTest {
public static void main(String[] args) throws SocketException{
NetworkInterface ni = NetworkInterface.getByName("eth0");
Enumeration<InetAddress> ias = ni.getInetAddresses();
for(;ias.hasMoreElements();){
InetAddress ia = ias.nextElement();
if(ia instanceof Inet4Address)
System.out.println(ia);
}
}
}
在我自己的电脑上运行,结果为空
NetworkInterface获取本机eth0网络接口IPv4地址
首先通过NetworkInterface的getByName静态方法,获取一个关于eth0的NetworkInterface实例,之后调用NetworkInterface的getInetAddress获取配置在eth0上的所有IP地址(这时有可能获取到多个IP,因为一个网络接口可以配置多个IP),通过遍历获取的InetAddress,判断如果是IPv4,则将这个IP地址输出出来
需要提示的是,一般每台计算机都会在别名为eth0的网络接口上配置公网的IPv4或IPv6的地址,因此,直接使用eth0,即可获取配置的IP地址信息,此外还有一个别名lo的网络接口,用来进行回环测试,其配置的IPv4一般为127.0.0.1
保守期间,防止有的计算机没有网络端口起名为eth0,更一般的方法是先通过NetworkInterface的静态方法getNetworkInterfaces获取本机的所有网络接口的父接口,之后遍历整个父接口获取下面的子接口,之后遍历子接口的IP地址,输出结果。并且在输出中分辨出IPv4的地址,还是IPv6的地址
通过NetworkInterface的静态方法
getNetworkInterfaces获取本机的所有网络接口的父接口,之后遍历整个父接口获取下面的子接口,之后遍历子接口的IP地址,输出接口。而且在输出中分辨出是IPv4的地址,还是IPv6的地址
代码实现
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Enumeration;
import java.net.NetworkInterface;
public class NetworkInterfaceTest2 {
public static void main(String[] args) throws SocketException {
NetworkInterface ni = null;
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
for(;nis.hasMoreElements();)
ni = nis.nextElement();
Enumeration<InetAddress> ias = ni.getInetAddresses();
for(;ias.hasMoreElements();){
InetAddress ia = ias.nextElement();
if(ia instanceof Inet4Address&&!ia.getHostAddress().equals("127.0.0.1"))
System.out.println("ipv4:"+ia);
else if(ia instanceof Inet6Address && !ia.equals(""))
System.out.println("ipv6:"+ia);
}
}
}