2013-03-01 85 views
4

我試圖用java.net.HttpURLConnection做一個簡單的HTTP GET呼叫和正在運行到的東西,我無法解釋:Java的HttpURLConnection的神祕死亡

public String makeGETCall(HttpURLConnection con) { 
    try { 
     System.out.println("About to make the request..."); 

     if(con == null) 
      System.out.println("con is NULL"); 
     else { 
      System.out.println("con is NOT null"); 

      if(con.getInputStream() == null) 
       System.out.println("con's input stream is NULL"); 
      else 
       System.out.println("con's input stream is NOT null"); 
     } 
    } catch(Throwable t) { 
     System.out.println("Error: " + t.getMessage()); 
    } 

    System.out.println("Returning...") 
    return "DUMMY DATA"; 
} 

當我運行它,我得到以下控制檯輸出:

About to make the request... 
con is NOT null 

然後程序終止,沒有錯誤。不會拋出異常,它不會意外退出,並且不會掛起或超時......它只會死亡。

當我檢查con.getInputStream()是否爲null似乎是要死的。但這仍然無法解釋爲什麼它只是安靜地死去,沒有任何錯誤跡象。有任何想法嗎?我很願意承認我可能錯誤地創建了HttpURLConnection,但仍然應該有更多跡象表明什麼是殺死我的程序......提前致謝!

+0

明顯的事情,但嘗試清理你的應用程序,並重新編譯。 – 2013-03-01 14:40:07

+0

我懷疑這是代碼中的錯誤。必須與項目相關。如果您在IDE中,請嘗試從命令行或新項目運行它。 – 2013-03-01 14:44:50

+0

我清理了我的項目,重新啓動了Eclipse並重新編譯。還是一樣。你爲什麼認爲這是與項目有關的,會導致潛在問題的是什麼?再次感謝! – IAmYourFaja 2013-03-01 14:45:59

回答

0

當我檢查con.getInputStream()是否爲空時,它似乎正在死亡。

那麼我覺得很難相信。

在表面上看來:

  • 測試參考,看它是否是null不能終止程序

  • con.getInputStream()可以拋出一個異常,或者返回

  • 如果確實返回它不應該返回null ...'因爲API不允許它...你會看到一條消息

  • 如果有異常被拋出,你會看到Error: ...消息

我的結論是,無論是不同的線程導致應用程序退出,或應用程序沒有退出的。

我能想到的唯一的其他解釋是編輯/編譯/部署/運行過程不起作用,而實際運行的代碼與您顯示的代碼不匹配。

我建議您嘗試爲此創建一個SSCCE,這樣其他人就可以重現它並找出實際發生的情況。

1

您的代碼不應該,因爲這行編譯:

System.out.println("Returning...") 

缺少一個分號。據說,我會想象你正在使用的應用程序的任何運行都使用舊的執行,並且沒有你可能編寫的新代碼。

如果情況並非如此,那麼您已經錯誤地粘貼了您的代碼(不知何故),我會冒險猜測您錯過了我們需要看到的其他方面?如果您已經以某種方式編輯了StackOverflow的代碼,您會介意共享原始代碼嗎?除非你有充分的理由,否則我會建議不要追趕Throwable。它通常是不好的做法,以掩蓋應用程序錯誤。

0

同樣問題在這裏。我追蹤了我的代碼,它永遠卡在con.getInputStream()中。 要重現問題,請運行下面的代碼示例。 (把你的正確的URL)

A)上的另一臺主機啓動任何HTTPS服務器

B)啓動客戶端代碼

C)關閉HTTPS服務器

d)啓動HTTPS服務器再次

- >卡在con.getInputStream()

雖然重新啓動HTTPS服務器,似乎在客戶端發生一些死鎖。 僅供參考我使用捆綁org.apache.felix.http.jetty作爲HTTP(S) - 服務器與附加Restlet Servlet。

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.security.KeyManagementException; 
import java.security.NoSuchAlgorithmException; 
import javax.net.ssl.HostnameVerifier; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 

public class TestHTTPS{ 

public static void main(String[] args) throws InterruptedException 
{ 
    new TestHTTPS().activate(); 
} 

private void activate() throws InterruptedException{ 

    TrustManager[] insecureTrustManager = new TrustManager[] { 
      new X509TrustManager() {  
       public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
        return null; 
       } 
       public void checkClientTrusted( 
        java.security.cert.X509Certificate[] certs, String authType) { 
        } 
       public void checkServerTrusted( 
        java.security.cert.X509Certificate[] certs, String authType) { 
       } 
      } 
     }; 


    try { 
     SSLContext sc = SSLContext.getInstance("SSL"); 
     sc.init(null, insecureTrustManager, new java.security.SecureRandom()); 
     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
    } catch (KeyManagementException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 

    HostnameVerifier allHostsValid = new HostnameVerifier() { 
     public boolean verify(String hostname, SSLSession session) { 
      return true; 
     } 
    }; 

    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 

    String https_url = "https://192.168.xx.xx:8443"; 
    URL url; 
    try { 

     url = new URL(https_url); 

     while(true) { 
      HttpsURLConnection con = (HttpsURLConnection)url.openConnection(); 
      con.setConnectTimeout(1000); 
      print_content(con); 
      Thread.sleep(100); 
     } 

    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

} 

private void print_content(HttpsURLConnection con){ 
    if(con!=null){ 

     try { 

      System.out.println("****** Content of the URL ********");   
      BufferedReader br = 
        new BufferedReader(
          new InputStreamReader(con.getInputStream())); 

      String input; 

      while ((input = br.readLine()) != null){ 
       System.out.println(input); 
      } 
      br.close(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

歡迎任何建議。

0

修正了它。

con.setReadTimeout(1000) 

顯然HTTP服務器接受連接,但在服務器啓動時錯誤連接時無法完成請求。 setReadTimeout會導致線程拋出SocketTimeoutException。

希望這可以幫助其他人來解決問題...

由於此問題而採用的Restlet與內部連接器也可能發生,這裏是的Restlet解決方案。你必須自己照顧的HostnameVerifier和一個SSLContextFactory:

context = new Context(); 

context.getParameters().add("readTimeout", Integer.toString(1000)); 
context.getAttributes().put("sslContextFactory", new YourSslContextFactory()); 
context.getAttributes().put("hostnameVerifier", new YourHostnameVerifier()); 

client = new Client(context, Protocol.HTTPS); 

確保

org.restlet.ext.ssl 
org.restlet.ext.net 
org.restlet.ext.httpclient 

在類路徑中。

最好的問候