JAVA socket 關於DNS 緩衝

來源:互聯網
上載者:User

在通過DNS尋找網域名稱的過程中,可能會經過多台中間DNS伺服器才能找到指定的網域名稱,因此,在DNS伺服器上尋找網域名稱是非常昂貴的操作。在Java中為了緩解這個問題,提供了DNS緩衝。當InetAddress類第一次使用某個網域名稱(如www.csdn.net)建立InetAddress對象後,JVM就會將這個網域名稱和它從DNS上獲得的資訊(如IP地址)都儲存在DNS緩衝中。當下一次InetAddress類再使用這個網域名稱時,就直接從DNS緩衝裡獲得所需的資訊,而無需再訪問DNS伺服器。

    DNS緩衝在預設時將永遠保留曾經訪問過的網域名稱資訊,但我們可以修改這個預設值。一般有兩種方法可以修改這個預設值:

    1. 在程式中通過java.security.Security.setProperty方法設定安全屬性networkaddress.cache.ttl的值(單位:秒)。如下面的代碼將緩衝逾時設為10秒:

java.security.Security.setProperty("networkaddress.cache.ttl", 10);

    2. 設定java.security檔案中的networkaddress.cache.negative.ttl屬性。假設JDK的安裝目錄是C:/jdk1.6,那麼java.security檔案位於c:/jdk1.6/jre/lib/security目錄中。開啟這個檔案,找到networkaddress.cache.ttl屬性,並將這個屬性值設為相應的緩衝逾時(單位:秒)。

    如果將networkaddress.cache.ttl屬性值設為-1,那麼DNS快取資料將永遠不會釋放。下面的代碼示範了使用和不使用DNS緩衝所產生效果:

package mynet;

import java.net.*;

public class MyDNS
{
    public static void main(String[] args) throws Exception
    {
        // args[0]: 本機名 args[1]:緩衝時間
        if (args.length < 2)
            return;
        java.security.Security.setProperty("networkaddress.cache.ttl", args[1]);
        long time = System.currentTimeMillis();
        InetAddress addresses1[] = InetAddress.getAllByName(args[0]);
        System.out.println("addresses1:   "
                        + String.valueOf(System.currentTimeMillis() - time)
                        + "毫秒");
        for (InetAddress address : addresses1)
            System.out.println(address);
        System.out.print("按任意鍵繼續");
        System.in.read();
        time = System.currentTimeMillis();
        InetAddress addresses2[] = InetAddress.getAllByName(args[0]);
        System.out.println("addresses2:   "
                        + String.valueOf(System.currentTimeMillis() - time)
                        + "毫秒");
        for (InetAddress address : addresses2)
            System.out.println(address);
    }
}

    在上面的代碼中設定了DNS緩衝逾時(通過args[1]參數),使用者可以通過命令列參數將這個值傳入MyDNS中。這個程式首先使用getAllByName建立一個InetAddress數組,然後通過System.in.read使程式暫停。當使用者等待一段時間後,可以按任意鍵繼續,並使用同一個網域名稱(args[0])再建立一個InetAddress數組。如果使用者等待的這段時間比DNS緩衝逾時小,那麼無論情況如何變化,addresses2和addresses1數組中的元素是一樣的,並且建立addresses2數組所花費的時間一般為0毫秒(小於1毫秒後,Java無法獲得更精確的時間)。

    測試1:

    執行如下命令(將DNS緩衝逾時設為5秒):

java mynet.MyDNS www.126.com 5

    運行結果1(在5秒之內按任意鍵):

addresses1:   344毫秒
www.126.com/202.108.9.77
按任意鍵繼續
addresses2:  0毫秒
www.126.com/202.108.9.77

    運行結果2(在5秒後按任意鍵):

addresses1:   344毫秒
www.126.com/202.108.9.77
按任意鍵繼續
addresses2:  484毫秒
www.126.com/202.108.9.77

    在上面的測試中可能出現兩個運行結果。如果在出現“按任意鍵繼續…”後,在5秒之內按任意鍵繼續後,就會得到運行結果1,從這個結果可以看出,addresses2所用的時間為0毫秒,也就是說,addresses2並未真正訪問DNS伺服器,而是直接從記憶體中的DNS緩衝得到的資料。當在5秒後按任意鍵繼續後,就會得到運行結果2,這時,記憶體中的DNS緩衝中的資料已經釋放,所以addresses2還得再訪問DNS伺服器,因此,addresses2的時間是484毫秒(addresses1和addresses2後面的毫秒數可能在不同的環境下的值不一樣,但一般情況下,運行結果1的addresses2的值為0或是一個接近0的數,如5.運行結果2的addresses2的值一般會和addresses1的值很接近,或是一個遠比0大的數,如1200)。

測試2:

    執行如下命令(ComputerName為原生電腦名稱,DNS緩衝逾時設為永不到期[-1]):

java mynet.MyDNS ComputerName -1

    運行結果(按任意鍵繼續之前,將192.168.18.20刪除):

addresses1:   31毫秒
myuniverse/192.168.18.10
myuniverse/192.168.18.20
按任意鍵繼續
addresses2:   0毫秒
myuniverse/192.168.18.10
myuniverse/192.168.18.20

    從上面的測試可以看出,將DNS緩衝設為永不到期後,無論過多少時間,按任意鍵後,addresses2任然得到了兩個IP地址(192.168.18.10和192.168.18.20),而且addresses2的時間是0毫秒,但在這時192.168.18.20已經被刪除。因此可以判斷,addresses2是從DNS緩衝中得到的資料。如果運行如下的命令,並在5秒後按任意鍵繼續後,addresses2就會只剩下一個IP地址(192.168.18.10)。

java mynet.MyDNS ComputerName 5

    如果網域名稱在DNS伺服器上不存在,那麼用戶端在進行一段時間的嘗試後(平均為5秒),就會拋出一個UnknownHostException異常。為了讓下一次訪問這個網域名稱時不再等待,DNS緩衝將這個錯誤資訊也儲存了起來。也就是說,只有第一次訪問錯誤網域名稱時才進行5稱左右的嘗試,以後再訪問這個網域名稱時將直接拋出UnknownHostException異常,而無需再等待5秒鐘,

    訪問網域名稱失敗的原因可能是這個網域名稱真的不存在,也可能是因為DNS伺服器或是其他的硬體或軟體的臨時故障,因此,一般不能將這個網域名稱錯誤資訊一直保留。在Java中可以通過networkaddress.cache.negative.ttl屬性設定保留這些資訊的時間。這個屬性的預設值是10秒。它也可以通過java.security.Security.setProperty方法或java.security檔案來設定。下面的代碼示範了networkaddress.cache.negative.ttl屬性的用法:

package mynet;

import java.net.*;

public class MyDNS1
{
    public static void main(String[] args) throws Exception
    {
        java.security.Security.setProperty("networkaddress.cache.negative.ttl",
                        "5");
        long time = 0;
        try
        {
            time = System.currentTimeMillis();
            InetAddress.getByName("www.ppp123.com");
        }
        catch (Exception e)
        {
            System.out.println("www.ppp123.com不存在! address1: "
                            + String.valueOf(System.currentTimeMillis() - time)
                            + "毫秒");
        }
        //Thread.sleep(6000); // 延遲6秒
        try
        {
            time = System.currentTimeMillis();
            InetAddress.getByName("www.ppp123.com");
        }
        catch (Exception e)
        {
            System.out.println("www.ppp123.com不存在! address2: "
                            + String.valueOf(System.currentTimeMillis() - time)
                            + "毫秒");
        }
    }
}

    在上面的代碼中將networkaddress.cache.negative.ttl屬性值設為5秒。這個程式分別測試了address1和address2訪問www.ppp123.com(這是個不存在的網域名稱,讀者可以將其換成任何不存在的網域名稱)後,用了多長時間拋出UnknownHostException異常。

    運行結果:

www.ppp123.com不存在! address1:  4688毫秒
www.ppp123.com不存在! address2:  0毫秒

    我們從上面的運行結果可以看出,address2使用了0毫秒就拋出了異常,因此,可以斷定address2是從DNS緩衝裡獲得了網域名稱www.ppp123.com不可訪問的資訊,所以就直接拋出了UnknowHostException異常。如果將上面代碼中的延遲代碼的注釋去掉,那麼可能得到如下的運行結果:

www.ppp123.com不存在! address1:  4688毫秒
www.ppp123.com不存在! address1:  4420毫秒

    從上面的運行結果可以看出,在第6秒時,DNS緩衝中的資料已經被釋放,因此,address2仍需要訪問DNS伺服器才能知道www.ppp123.com是不可訪問的網域名稱。

    在使用DNS緩衝時有兩點需要注意:

    1. 可以根據實際情況來設定networkaddress.cache.ttl屬性的值。一般將這個屬性的值設為-1.但如果訪問的是動態映射的網域名稱(如使用動態網域名稱服務 (DNS)將網域名稱映射成ADSL的動態IP), 就可能產生IP地址變化後,用戶端得到的還是原來的IP地址的情況。

    2. 在設定networkaddress.cache.negative.ttl屬性值時最好不要將它設為-1,否則如果一個網域名稱因為暫時的故障而無法訪問,那麼程式再次訪問這個網域名稱時,即使這個網域名稱恢複正常,程式也無法再訪問這個網域名稱了。除非重新運行程式。

 

【轉自www.bitsCN.com】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.