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
IP地址分类

代码实例
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()方法

  1. 定义: public byte[] getAddress()
  2. 该方法和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接口中定意思了一些方法,通过这些方法可以枚举对象集合中的元素

  1. boolean hasMoreElements()测试此枚举是否包含更多的元素
  2. 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);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值