面向基础系列之---Java网络编程---网络链接组件的使用(InetAddress)

这个系列是我一直想写的,由于从入职第一年的第一个月开始(那时还在zte),我就买了网络上惟一的一本,写Java网络的书籍:《Java网络编程》。当时功底通常,感受看起来,仍是不少云里雾里,尤为是前面几章介绍使用Java的基础网络链接对象的时候,尤甚!随着工做的开展,工程的深刻,经常会碰到要下载一个问价、链接远端url获取数据、下载压缩包等网络通讯相关的业务需求,这个时候,对于Java网络方面的支持对象的熟悉,就尤其关键。再到后面的后面,随着NIO的兴起,各大框架对底层网络优化的跟进,我以为Java网络编程,已经成为服务端开发一个重中之重。没有个好身体,何谈加班工做升值加薪呢?恩,让咱们来好好锻炼身体吧。java

1、java.net.InetAddress 相关

Java中对IP地址的一个抽象,全部的上层socket对象,底层都是要用到这个类的,通常来说,这东西包含了一个 主机名和一个IP地址编程

一、建立一个InetAddress对象

import java.net.*;

public class NetworkMain {
    public static void main(String[] args) {
        try {
//            InetAddress inetAddress = InetAddress.getByName("www.baidu1121.com");//Exception
            InetAddress inetAddress = InetAddress.getByName("www.baidu.com");//输出:www.baidu.com/14.215.177.38
            System.out.println(inetAddress);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}
  1. 注意相关输出,getByName是要进行网络链接,查找DNS的
  2. InetAdress对象重载了toString方法,结果是“域名/ip地址”
  3. 这个IntetAdress对象会对查找的对象进行缓存,第一次网络链接,其余的时候,查找本地缓存
  4. 若是是一个错误,差很少的域名,会报java.net.UnknownHostException异常

二、java.net.InetAddress的一些其余工程方法使用

import java.net.*;

public class NetworkMain {
    public static void main(String[] args) {
        try {
            InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
            System.out.println("能够传入具体的Ip地址返回主机名:" + inetAddress.getHostName());//若是没有主机名,会直接打印ip地址

            InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");
            for (InetAddress it : allByName) {
                System.out.println("返回域名对应的全部地址:" + it);
            }

            InetAddress localHost = InetAddress.getLocalHost();
            System.out.println("本地机器名称与地址:" + localHost);

            byte[] address = {107, 23, 11, (byte) 154};
            InetAddress byAddress = InetAddress.getByAddress(address);
            System.out.println("不用进行DNS查询解析的方式:"+byAddress);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}
  1. 要知道大部分方法都是要与DNS进行网络交互的。可是比较亲民的点是,大部分都会被本地缓存
  2. getByAddress()这个很特殊,这个是不与DNS交互
  3. 获取本地的InetAdress的时候,获取到的是机器名/本地地址
  4. getByName()使用ip地址进行查找的时候,是不会进行远端通讯的,只有显示调用getHostName()的时候才会进行域名解析。即便找不到主机名,也不会抛出java.net.UnknownHostException,会返回原ip地址

三、获取java.net.InetAddress内部对象的相关方法

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

java.net.InetAddress是没有对应的set相关方法的,这说明这个类是没法使用java.net以外的类进行修改的,因此这个类也是不可变的,所以是线程安全的数组

  1. getHostName是会进行DNS查询的,若是能够获取到相关主机名,会返回:主机名/ip,这个解构。若是获取不到相关的DNS域名或者主机名的状况下,会返回ip地址。这个方法或进行域名缓存
  2. getCanonicalHostName相较于getHostName会积极一些。不会不论是否是第一次获取,都会进行DNS的查询,就是说,都会进行网络请求,而且获取到的话,会刷新原先缓存的主机名
  3. getHostAddress返回机器的ip地址,没什么好说的。getAddress这个会返回一个无符号的地址数组,ipv4会有4个的长度,ipv6会有16个的长度,能够用这个判断当前是否使用的是ipv4仍是ipv6。固然Java中无符号的转换也是一个小小的tips
import java.net.*;
import java.util.Objects;

public class NetworkMain {
    public static void main(String[] args) {
        try {
            InetAddress localHost = InetAddress.getLocalHost();
            byte[] address = localHost.getAddress();
            int version = getversion(address);
            System.out.println("当前地址类型是:ipV" + version);
            String resultAddress = getUnsigeAdressString(address);
            System.out.println("当前地址是:"+resultAddress);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

    /**
     * 对无符号地址的转换
     */
    private static String getUnsigeAdressString(byte[] address) {
        if (Objects.isNull(address)) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (byte it : address) {
            int unsignedByte = it < 0 ? it + 256 : it;
            sb.append(unsignedByte);
            sb.append(".");
        }
        return sb.substring(0,sb.length()-1);
    }

    /**
     * 获取当前地址是ipv4仍是ipv6
     */
    private static int getversion(byte[] address) {

        if (address.length == 4) return 4;
        else if (address.length == 16) return 6;
        else return -1;
    }
}

四、可达性测试与相等的断定

一、 public boolean isReachable(int timeout) throws IOException缓存

这个方法使用ICMP协议发送echo请求,断定InetAddress包装的地址是否可以联通,表现形式是:安全

  • timeout内响应,方法返回true
  • timeout内没法响应,方法返回false
  • 网络错误,抛IOException异常

二、 public boolean isReachable(NetworkInterface interface, int ttl, int timeout)网络

这个方法与上一个相似,只不过加了两个参数app

  • interface:从哪一个网口进行测试
  • ttl:生存时间(链接被丢弃前尝试最大的网络跳数)

三、 相等性断定框架

  • 两个InetAdress相等的断定,不用域名相同,只要两个对象的映射ip是同一个,equals方法就会返回true
  • hashCode方法使用的哈希值,是根据InetAdress的ip地址进行的哈希

2、java.net.NetworkInterface使用

这东西,表示一个本地的物理硬件和虚拟地址,因此不能本身进行构建。能够经过ip地址、名字或者枚举来请求一个NetworkInterfacesocket

一、 public static NetworkInterface getByName(String name) throws SocketException

这个对象返回指定网络接口的对象,若是没有这个接口,返回null,若是查找相关本地网络接口时候,底层网络栈出现问题,则抛出SocketException异常oop

try{
    NetworkInterface ni = NetworkInterface.getByName("eth0");
    if(ni == null){
        System.err.printIn("no such interface: ehto");
    }
    
}catch (SocketException ex){
    System.err.println(Could not list socket.);
}

二、 public static NetworkInterface getByInetAddress(InetAddress addr) throws SocketException

返回对应的InetAdress对象绑定的接口,若是本地主机上面没有这个网络接口与这个ip进行绑定,返回null。若是发生错误,则抛出SocketException异常。

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;

public class NetworkMain {
    public static void main(String[] args) {
        try {
            InetAddress byName = InetAddress.getByName("127.0.0.1");
            NetworkInterface byInetAddress = NetworkInterface.getByInetAddress(byName);
            if(byInetAddress==null){
                System.err.println("no local loopback address,");
            }
            System.out.println(byInetAddress);//结果:name:lo0 (lo0)
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        }

    }

}

三、 public static Enumeration<NetworkInterface> getNetworkInterfaces()throws SocketException

这个方法可以遍历全部的本地网卡或者虚拟网卡,返回的是一个Enumeration对象

import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

public class NetworkMain {
    public static void main(String[] args) {
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()){
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                System.out.println(networkInterface);
                /*返回:(macOS下面的输出,可见是没有ip地址的)
                    name:en7 (en7)
                    name:utun0 (utun0)
                    name:awdl0 (awdl0)
                    name:en0 (en0)
                    name:lo0 (lo0)
                * */
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

}
相关文章
相关标签/搜索