2012-08-07 74 views
1

我正在實施一種Java方法,用於在加載網頁時測量許多指標。這些指標包括:解決時間,連接時間和下載時間。有效測量dns查找和網站內容下載時間

所面臨的挑戰似乎是名稱解析,因爲代碼不應該引發以任何方式 NS看起坐(即使DNS緩存被禁用)。

我的第一個想法是在連接到服務器之前觸發名稱解析,然後阻止java在連接時運行第二個名稱。 使用InetAddress.getByName()進行名稱查找,然後使用HttpURLConnection和它的setRequestProperty方法來設置主機標頭似乎有竅門。

所以這裏是我的問題:下面的那兩個片段是否有相同的效果?他們總是對所有可能的主機給出完全相同的結果嗎?如果不是,我還有什麼其他選擇?

版本一:隱名解析

/** 
* Site content download Test 
* 
* @throws IOException 
*/ 
public static void testMethod() throws IOException { 

    String protocol = "http"; 
    String host = "stackoverflow.com"; 
    String file = "/"; 

    // create a URL object 
    URL url = new URL(protocol, host, file); 

    // create the connection object 
    HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 

    // connect 
    conn.connect(); 

    // create a stream reader 
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
    String inputLine; 

    // read contents and print on std out 
    while ((inputLine = in.readLine()) != null) { 
     System.out.println(inputLine); 
    } 

    // close the stream 
    in.close(); 
} 

版本2:明確名稱解析

/** 
* Enhanced Site content download Test 
* 
* @throws IOException 
*/ 
public static void testMethod2() throws IOException { 

    String protocol = "http"; 
    String host = "stackoverflow.com"; 
    String file = "/"; 

    // Do a name lookup. 
    // If a literal IP address is supplied, only the validity of the address format is checked. 
    InetAddress address = InetAddress.getByName(host); 

    // create a URL object 
    URL url = new URL(protocol, address.getHostAddress(), file); 

    // create the connection object 
    HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 

    // allow overriding Host and other restricted headers 
    System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); 

    // set the host header 
    conn.setRequestProperty("Host", host); 

    // connect 
    conn.connect(); 

    // create a stream reader 
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
    String inputLine; 

    // read contents and print on std out 
    while ((inputLine = in.readLine()) != null) { 
     System.out.println(inputLine); 
    } 

    // close the stream 
    in.close(); 
} 

TIA的幫助。 -Dimi

回答

1

我已經通過Java的源代碼,看看當你在NetworkClient.doConnect傳遞一個域名HttpURLConnection類,它最終最終會發生什麼瀏覽:

if (connectTimeout >= 0) { 
      s.connect(new InetSocketAddress(server, port), connectTimeout); 
     } else { 
      if (defaultConnectTimeout > 0) { 
       s.connect(new InetSocketAddress(server, port), defaultConnectTimeout); 
      } else { 
       s.connect(new InetSocketAddress(server, port)); 
      } 
     } 

正如你看到的,域名解析是總是InetSocketAddress處理:

public InetSocketAddress(String hostname, int port) { 
    if (port < 0 || port > 0xFFFF) { 
     throw new IllegalArgumentException("port out of range:" + port); 
    } 
    if (hostname == null) { 
     throw new IllegalArgumentException("hostname can't be null"); 
    } 
    try { 
     addr = InetAddress.getByName(hostname); 
    } catch(UnknownHostException e) { 
     this.hostname = hostname; 
     addr = null; 
    } 
    this.port = port; 
} 

正如你所看到的,InetAddress.getByName被稱爲每次。我認爲你的方法是安全的。

+0

所以基本上我們可以聲稱HttpClient類,當它獲得一個主機名而不是一個IP地址時,與我的第二個方法的行爲類似,因此沒有真正的區別。我也自己研究了openjdk的源代碼,我認爲你所說的是真實的。我會等一會兒,看看是否有任何異議,然後接受你的答案。感謝您查看這個。 – dimi 2012-08-08 07:45:15

+0

我創建了一個測試方法,使用這兩種方法測試20個網站的樣本,對於那些在每次頁面加載時都不更改其內容的網站,結果都是相同的。我還測試了它對本地apache服務器和收到的標頭是相同的。我接受你的答案,因爲它證實了我的觀察。謝謝。 – dimi 2012-08-08 16:03:33