面向基礎系列之---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();
        }
    }

}
相關文章
相關標籤/搜索