2013-06-20 29 views
2

我得到EOFException當我所說的REST API。我知道它說響應爲空。但它不應該。我在iOS應用程序中使用相同的API沒有任何問題。獲取java.io.EOFException的使用HttpURLConnection的

這裏是我的代碼:

try { 
    url = new URL(baseUrl); 
} 
    // Thrown when URL could not be parsed 
    catch (MalformedURLException me) { 
     Log.e(TAG, "URL could not be parsed. URL : " + baseUrl, me); 
    } 
    try { 

    //  System.setProperty("http.keepAlive", "false"); 

    // Set connection properties 
    urlConnection = (HttpURLConnection) url.openConnection(); 
    urlConnection.setRequestMethod(method); 
    urlConnection.setConnectTimeout(TIMEOUT * 1000); 
    urlConnection.setChunkedStreamingMode(0); 
    urlConnection.setRequestProperty("Accept", "*/*"); 
    urlConnection.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); 

    //  urlConnection.setRequestProperty("Connection", "close"); 

    if (method.equals("POST") || method.equals("PUT")) { 
     // Set to true when posting data 
     urlConnection.setDoOutput(true); 

     // Write data to post to connection output stream 
     OutputStream out = urlConnection.getOutputStream(); 
     out.write(postParameters.getBytes("UTF-8")); 
     Log.d(TAG, "Data written to output stream."); 
    } 

    //  urlConnection.connect(); 

    try { 
     // Get response 
     in = new BufferedInputStream(urlConnection.getInputStream()); 
    } catch (IOException e) { 
      Log.e(TAG, 
        "Exception in getting connection input stream. Input stream : " 
           + in, e); 
    } 

    Log.d(TAG, "content length : " + urlConnection.getContentLength()); 
    Log.d(TAG, "content type : " + urlConnection.getContentType()); 

    // Read the input stream that has response 
    statusCode = urlConnection.getResponseCode(); 
    Log.d(TAG, "Status code : " + statusCode); 

    if (statusCode >= 400) { 
     Log.e(TAG, "Error stream : " + urlConnection.getErrorStream().toString()); 
    } 
    // Passing input stream to a function.   
    readStream(in, statusCode); 
} catch (ProtocolException pe) { 
    Log.e(TAG, 
        "Make sure HTTP method is set before connecting to URL. Line : " 
          + getLineNumber(), pe); 
} catch (IllegalStateException ie) { 
    Log.e(TAG, 
        "Set connection properties before connecting to URL. Line : " 
          + getLineNumber(), ie); 
} 
// Thrown when connecting to URL times out 
catch (SocketTimeoutException se) { 
    Log.e(TAG, "Timeout before connecting to URL : " + baseUrl 
        + ". Line : " + getLineNumber(), se); 


} catch (IOException e) { 
    Log.e(TAG, "Exception while connecting to URL : " + baseUrl, e); 
} finally { 
    urlConnection.disconnect(); 
} 

我曾嘗試下面的東西,但沒有奏效。論文在代碼中被註釋掉。 :

1)System.setProperty("http.keepAlive", "false");
2)urlConnection.setRequestProperty("Connection", "close");
3)urlConnection.connect();

語句Log.d(TAG, "Status code : " + statusCode);是沒有得到記錄。通常它工作。

logcat的屏幕截圖:

enter image description here

回答

1

顯然,這是由於在HttpURLConnection的一個bug(見this answer on StackOverflow)。我建議你實施一個重試機制。這是我已經實施,例如:

/** POST an object on the server using the REST API. */ 
private int httpPOST(String path, JSONObject json) { 
    final static int MAX_RETRIES = 3; 
    int numTries = 0; 
    int responseCode = 0; 
    HttpsURLConnection urlConnection = null; 
    final long startTime = System.currentTimeMillis(); 

    while (numTries < MAX_RETRIES) { 

     if (numTries != 0) { 
      LOGV(TAG, "Retry n°" + numTries); 
     } 

     // Create (POST) object on server 
     try { 
      byte[] bytes = json.toString().getBytes("UTF-8"); 
      URL url = new URL(path); 
      urlConnection = (HttpsURLConnection) url.openConnection(); 
      urlConnection.setDoOutput(true); 
      urlConnection.setFixedLengthStreamingMode(bytes.length); 
      urlConnection.setRequestProperty("Content-Type", "application/json;charset=utf-8"); 
      LOGV(TAG, "HTTP POST " + url.toString()); 
      OutputStream out = urlConnection.getOutputStream(); 
      out.write(bytes); 
      out.close(); 
      responseCode = urlConnection.getResponseCode(); 
      LOGV(TAG, "HTTP POST response code: " + responseCode + " (" + (System.currentTimeMillis() - startTime) 
        + "ms)"); 
      return responseCode; 

     } catch (UnsupportedEncodingException e) { 
      LOGV(TAG, "Unsupported encoding exception"); 
     } catch (MalformedURLException e) { 
      LOGV(TAG, "Malformed URL exception"); 
     } catch (IOException e) { 
      LOGV(TAG, "IO exception: " + e.toString()); 
      // e.printStackTrace(); 
     } finally { 

      if (urlConnection != null) 
       urlConnection.disconnect(); 
     } 

     numTries++; 
    } 

    LOGV(TAG, "Max retries reached. Giving up..."); 

    return responseCode; 

} 
1

下面的代碼可以幫助你

HttpEntity entity = response.getEntity(); 

// All the work is done for you here :) 
String jsonContent = EntityUtils.toString(entity); 

// Create a Reader from String 
Reader stringReader = new StringReader(jsonContent); 

// Pass the string reader to JsonReader constructor 
JsonReader reader = new JsonReader(stringReader); 
reader.setLenient(true); 
readGson(reader); 

... 
// at the end of method return the JSON response 
return jsonContent; 
1

這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,使用該代碼。

注意:Android pre-Froyo(2.2)有一些與保持活動連接相關的錯誤 - 請參閱博客文章:http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html。雖然很多StackOverflow的答案都提到了它,但我仍然沒有看到有關新版本Android的錯誤的令人信服的證據(因此,爲什麼我將它置於多個位置......)

相關問題