2013-06-20 9 views
2

Я получаю EOFException, когда я называю REST API. Я знаю, что он говорит, что ответ равен нулю. Но это не должно. Я использую тот же API в приложении iOS без каких-либо проблем.Получение 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 (см 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 отлично справляется с ответами на сервер, но я получаю EOFException на Android с помощью HttpURLConnection.

Мой сервер использует питон SimpleHTTPServer, и я был ошибочно предполагая, все, что мне нужно сделать, чтобы указать успех был следующий:

self.send_response(200) 

Это посылает начальную строку заголовка ответа, сервер и заголовок даты, но оставляет поток в состоянии, в котором вы также можете отправлять дополнительные заголовки. HTTP требует дополнительной новой строки после заголовков, чтобы указать, что они завершены. Если эта новая строка отсутствует, когда вы пытаетесь получить тело ввода InputStream или код ответа и т. Д. С HttpURLConnection, тогда он выдает исключение EOFException (что на самом деле разумно, думая об этом). Некоторые HTTP-клиенты действительно принимали короткий ответ и сообщали код результата успеха, который привел ко мне, возможно, несправедливо указывая пальцем на HttpURLConnection.

Я изменил мой сервер, чтобы сделать это вместо того, чтобы:

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

Нет больше EOFException с этим кодом.

NB: На Android pre-Froyo (2.2) есть некоторые ошибки, связанные с подключением keep-alive - см. Запись в блоге здесь: http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html. Я еще не вижу убедительных доказательств ошибок с новыми версиями Android, хотя многие ответы StackOverflow упоминают об этом (поэтому, я полагаю, это в разных местах ...)

 Смежные вопросы

  • Нет связанных вопросов^_^