IPv6基本編程——Java

來源:互聯網
上載者:User

標籤:鍵盤輸入   mda   exception   pack   過濾   click   exce   思路   存在   

IPv6編程——Java1. Java支援IPv6

Java 從 1.4 版開始支援 Linux 和Solaris 平台上的 IPv6。1.5 版起又加入了 Windows 平台上的支援。
在 IPv6 的環境下開發 Java 應用,或者移植已有的 IPv4 環境下開發的Java 應用到 IPv6 環境中來,對於 IPv6 網路地址的驗證是必須的步驟,尤其是對那些提供了 UI(使用者介面)的 Java 應用。

2. 擷取本機IPv6地址

有時為了能夠註冊 listener,開發人員需要使用原生 IPv6 地址,這一地址不能簡單得通過 InetAddress.getLocalhost() 獲得。因為這樣有可能獲得諸如 0:0:0:0:0:0:0:1 這樣的特殊地址。使用這樣的地址,其他伺服器將無法把通知發送到本機上,因此必須先進行過濾,選出確實可用的地址。以下代碼實現了這一功能,思路是遍曆網路介面的各個地址,直至找到符合要求的地址。

package com.text;import java.io.IOException;import java.net.Inet6Address;import java.net.InetAddress;import java.net.NetworkInterface;import java.util.Enumeration;public class Get_IPv6 {    public static void main(String[] args) throws IOException{        String str = getLocalIPv6Address();        System.out.println(str);    }    public static String getLocalIPv6Address() throws IOException {        InetAddress inetAddress = null;        Enumeration<NetworkInterface> networkInterfaces =        NetworkInterface        .getNetworkInterfaces();        outer:        while (networkInterfaces.hasMoreElements()) {            Enumeration<InetAddress> inetAds =            networkInterfaces.nextElement()            .getInetAddresses();            while (inetAds.hasMoreElements()) {                inetAddress = inetAds.nextElement();        //Check if it‘s ipv6 address and reserved address                if (inetAddress instanceof Inet6Address                    && !isReservedAddr(inetAddress)) {                    break outer;            }        }    }    String ipAddr = inetAddress.getHostAddress();    // Filter network card No    int index = ipAddr.indexOf(‘%‘);    if (index > 0) {        ipAddr = ipAddr.substring(0, index);    }    return ipAddr;    }    private static boolean isReservedAddr(InetAddress inetAddr) {        if (inetAddr.isAnyLocalAddress() || inetAddr.isLinkLocalAddress()            || inetAddr.isLoopbackAddress()) {            return true;    }    return false;    }}

為了支援 IPv6,Java 中增加了兩個 InetAddress 的子類:Inet4Address和 Inet6Address。一般情況下這兩個子類並不會被使用到,但是當我們需要分別處理不同的 IP 協議時就非常有用,在這我們根據Inet6Address來篩選地址。
isReservedAddr() 方法過濾了本機特殊 IP 位址,包括“LocalAddress”,“LinkLocalAddress”和“LoopbackAddress”。另一個需要注意的地方是:在 windows 平台上,取得的 IPv6 地址後面可能跟了一個百分比符號加數字。這裡的數字是本機網路介面卡的編號。這個尾碼並不是 IPv6 標準地址的一部分,可以去除。

3. IPv4/IPv6 雙環境下,網路的選擇和測試

Java 提供了 InetAddress 的兩個擴充類以供使用:Inet4Address 和 Inet6Address,其中封裝了對於 IPv4 和 IPv6 的特殊屬性和行為。然而由於Java 的多態特性,使得程式員一般只需要使用父類 InetAddress,JAVA 虛擬機器可以根據所封裝的 IP 位址類型的不同,在運行時選擇正確的行為邏輯。所以在多數情況下,程式員並不需要精確控制所使用的類型及其行為,一切交給 Java虛擬機器即可。具體的新增類型及其新增方法,請具體參閱 Sun 公司的 JavaDoc。
在 IPv4/IPv6 雙環境中,對於使用 Java 開發的網路應用,比較值得注意的是以下兩個 IPv6 相關的 JAVA 虛擬機器系統屬性。
java.net.preferIPv4Stack=<\true|false>
java.net.preferIPv6Addresses=<\true|false>
程式中設定代碼如下:
System.setProperty("java.net.preferIPv6Addresses","true");
preferIPv4Stack(預設 false)表示如果存在 IPv4 和 IPv6 雙棧,Java 程式是否優先使用 IPv4 通訊端。預設值是優先使用 IPv6 通訊端,因為 IPv6 通訊端可以與對應的 IPv4 或 IPv6 主機進行對話;相反如果優先使用 IPv4,則只不能與 IPv6 主機進行通訊。
preferIPv6Addresses(預設 false)表示在查詢本地或遠端 IP 位址時,如果存在 IPv4 和 IPv6 雙地址,Java 程式是否優先返回 IPv6 地址。Java 預設返回 IPv4 地址主要是為了向後相容,以支援舊有的 IPv4 驗證邏輯,以及舊有的僅支援 IPv4 地址的服務。

4. socket 支援 IPv6 通訊樣本

用戶端:

package com.text2;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.net.Inet6Address;import java.net.InetAddress;import java.net.NetworkInterface;import java.net.Socket;import java.util.Enumeration;public class Click {    public static void main(String[] args) throws IOException {        //擷取本機IPv6地址getLocalIPv6Address()方法在上面已經提到        String servernameString = getLocalIPv6Address();        System.out.println("用戶端啟動…");        System.out.println("當接收到伺服器端字元為 \"OK\" 的時候, 用戶端將終止\n");        while (true) {            Socket socket = null;            try {                // 建立一個流通訊端並將其串連到指定主機上的指定連接埠號碼                socket = new Socket(servernameString, 8080);                // 讀取伺服器端資料                DataInputStream input = new DataInputStream(socket.getInputStream());                // 向伺服器端發送資料                DataOutputStream out = new DataOutputStream(socket.getOutputStream());                System.out.print("請輸入: \t");                String str = new BufferedReader(new InputStreamReader(System.in)).readLine();                out.writeUTF(str);                String ret = input.readUTF();                System.out.println("伺服器端返回過來的是: " + ret);                if ("OK".equals(ret)) {                    System.out.println("用戶端將關閉串連");                    Thread.sleep(500);                    break;                }                out.close();                input.close();            } catch (Exception e) {                System.out.println("用戶端異常:" + e.getMessage());            } finally {                if (socket != null) {                    try {                        socket.close();                    } catch (IOException e) {                        socket = null;                        System.out.println("用戶端 finally 異常:" + e.getMessage());                    }                }            }        }    }    public static String getLocalIPv6Address() throws IOException {        InetAddress inetAddress = null;        Enumeration<NetworkInterface> networkInterfaces =        NetworkInterface        .getNetworkInterfaces();        outer:        while (networkInterfaces.hasMoreElements()) {            Enumeration<InetAddress> inetAds =            networkInterfaces.nextElement()            .getInetAddresses();            while (inetAds.hasMoreElements()) {                inetAddress = inetAds.nextElement();        //Check if it‘s ipv6 address and reserved address                if (inetAddress instanceof Inet6Address                    && !isReservedAddr(inetAddress)) {                    break outer;                }            }        }        String ipAddr = inetAddress.getHostAddress();        // Filter network card No        int index = ipAddr.indexOf(‘%‘);        if (index > 0) {            ipAddr = ipAddr.substring(0, index);        }        return ipAddr;    }    private static boolean isReservedAddr(InetAddress inetAddr) {        if (inetAddr.isAnyLocalAddress() || inetAddr.isLinkLocalAddress()|| inetAddr.isLoopbackAddress()) {            return true;            }                return false;    }}

伺服器端:

package com.text2;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;public class Server {    public static void main(String[] args) {        // TODO Auto-generated method stub        System.out.println("伺服器啟動…\n");        Server server = new Server();        server.init();    }    public void init() {        try {            ServerSocket serverSocket = new ServerSocket(8080);            while (true) {                // 一旦有堵塞, 則表示伺服器與用戶端獲得了串連                Socket client = serverSocket.accept();                // 處理這次串連                new HandlerThread(client);            }        } catch (Exception e) {            System.out.println("伺服器異常: " + e.getMessage());        }    }    private class HandlerThread implements Runnable {        private Socket socket;        public HandlerThread(Socket client) {            socket = client;            new Thread(this).start();        }        public void run() {            try {                // 讀取用戶端資料                DataInputStream input = new DataInputStream(socket.getInputStream());                String clientInputStr = input.readUTF();                //這裡要注意和用戶端輸出資料流的寫方法對應,否則會拋 EOFException                // 處理用戶端資料                System.out.println("用戶端發過來的內容:" + clientInputStr);                // 向用戶端回複資訊                DataOutputStream out = new DataOutputStream(socket.getOutputStream());                System.out.print("請輸入:\t");                // 發送鍵盤輸入的一行                String s = new BufferedReader(new InputStreamReader(System.in)).readLine();                out.writeUTF(s);                out.close();                input.close();            } catch (Exception e) {                    System.out.println("伺服器 run 異常: " + e.getMessage());            } finally {                if (socket != null) {                    try {                        socket.close();                    } catch (Exception e) {                        socket = null;                        System.out.println("服務端 finally 異常:" + e.getMessage());                    }                }            }        }    }}

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

    

IPv6基本編程——Java

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.