1

我使用後下面的代碼請求HttpsURLConnection的EOFException類

public String executeHttpPost(String uri, String data) { 

    HttpURLConnection conn = null; 
    URL url = null; 
    String s = null; 

    try { 

     url = new URL(uri); 

     conn = (HttpURLConnection) url.openConnection(); 

     if (conn instanceof HttpsURLConnection) { 
      Log.d("HTTPS", "HttpsUrl"); 
     } 

     conn.setDoOutput(true); 
     conn.setDoInput(true); 
     conn.setRequestMethod("POST"); 
     conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 

     OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); 
     wr.write(data); 
     wr.flush(); 

     DisplayResponseHeaders(conn); 

     s = readStream(conn.getInputStream()); 
     Log.d("body", s); 

    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     s = null; 
     e.printStackTrace(); 
    } finally { 
     conn.disconnect(); 
    } 
    return s; 
    } 

當我使用它通過HTTP,一切運作良好,但通過https我得到

java.io.EOFException 
at libcore.io.Streams.readAsciiLine(Streams.java:203) 
at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:573) 
at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:821) 
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:283) 
libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177) 
libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271) 
ru.fors.remsmed.fragment.NetHelper.executeHttpPost(NetHelper.java:234) 
ru.fors.remsmed.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:424) 
ru.fors.remsmed.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:1) 
android.os.AsyncTask$2.call(AsyncTask.java:287) 
java.util.concurrent.FutureTask.run(FutureTask.java:234) 
android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
java.lang.Thread.run(Thread.java:856) 
threadid=14: thread exiting with uncaught exception (group=0x40a71930) 

,我發現這個問題有關在httpsurlconnection和可能的解決方案中回收連接bug:

if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) { 
    conn.setRequestProperty("Connection", "close"); 
} 

但它不適用於我。

回答

1

試圖改變你的代碼是這樣的:

conn.setRequestProperty("Content-Type", 
          "application/x-www-form-urlencoded; charset: UTF-8"); 
    byte[] output = data.getBytes("UTF-8"); 
    conn.setFixedLengthStreamingMode(output.length); 

    os = conn.getOutputStream(); 
    os.write(output); 
    os.flush(); 
    os.close(); 

    DisplayResponseHeaders(conn); 

    if (conn.getResponseCode() == 200) { // or other 2xx code like 204 

     s = readStream(conn.getInputStream()); 
     Log.d("body", s); 
    } 
    else { 

     // handle error conditions like 404, 400, 500, ... 

     // now it may be necessary to read the error stream 

     InputStream errorStream = conn.getErrorStream(); 

     // ... 
    } 

據我所知,你應該總是關閉所有流已打開。我不確定conn.disconnect()是否適合你。

如果您想更方便地爲您的HTTP(S)請求編碼,您可以查看DavidWebb,其中有一個庫列表幫助您避免使用繁瑣的HttpURLConnection。

0

EOFException表示響應格式錯誤 - 可能缺少標題後面的空白行。一些HTTP客戶端代碼是在這種情況下更多的寬容,對我的iOS可以處理我的服務器響應很好,但我使用HttpURLConnection的Android變得EOFException類。

我的服務器是使用python SimpleHTTPServer,我被錯誤地假定所有我需要做的,表示成功是以下幾點:

self.send_response(200) 

這發出的初始響應標題行,服務器和日期頭,但將流保持在您可以發送其他標題的狀態。 HTTP需要在標題後添加一個新行以表示它們已完成。如果在嘗試使用HttpURLConnection獲取結果體InputStream或響應代碼等時未出現此新行,則會顯示EOFException(實際上這是合理的,考慮它)。一些HTTP客戶端沒有接受短的響應和報道的成功結果代碼,導致我也許不公平指着HttpURLConnection的手指。

我改變了我的服務器要做到這一點,而不是:

self.send_response(200) 
self.send_header("Content-Length", "0") 
self.end_headers() 

沒有更多EOFException,使用該代碼。有可能「連接:關閉」解決方案在某些服務器上觸發某些行爲(例如,確保響應在關閉之前有效),但python SimpleHTTPServer並非如此,根本原因竟然是我的錯。

注意:Android pre-Froyo(2.2)有一些與保持活動連接相關的錯誤 - 請參閱博客文章:http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html。我還沒有看到使用新版Android的錯誤的令人信服的證據。