Подтвердить что ты не робот

Android HttpURLConnection бросает EOFException

Здесь вопрос прост.

Я создаю HTTPS-соединение с моим сервером через прокси-сервер, используя объект HttpUrlConnection.

Мой прокси закрывает соединение, но мой код по-прежнему пытается повторно использовать одно и то же соединение. И поэтому я получаю EOFException.

Как обращаться с такими случаями?

4b9b3361

Ответ 1

Я бы рекомендовал отключить свойство http.keepalive system. Раздел производительности документации указывает, что соединения сокетов будут использоваться повторно, когда это возможно. Похоже, он пытается повторно использовать соединение, но прокси уже закрыл его. На этот пост Даррелл также указывает, что изменение системного свойства решило его проблему.

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

Ответ 2

Оказывается, они исправили эту проблему в Android 8 января [1]. Исправление в основном отмечает старое соединение как переработанное и внутренне повторяет запрос.

Чтобы исправить это сейчас, я бы предложил повторить запросы, если встречается исключение EOFException с лимитом повтора, чтобы предотвратить stackoverlows.

Ответ 3

У меня была эта проблема с обычными HTTP-соединениями. Первый запрос прошел нормально, второй с ошибкой EOFException.

Попутно я исправил его, удалив...

urlConnection.setChunkedStreamingMode(0);

... из HttpUrlConnection.

Я мог бы сказать, что веб-сервер, с которым я звоню, не может хорошо обрабатывать данные chuncked. Не знаю.

Ответ 4

Если вы не хотите повторно использовать соединение, отпустите его.

 finally {
     urlConnection.disconnect();
   }

Ответ 5

Вам не следует пытаться повторно использовать один и тот же экземпляр HttpURLConnection. docs в самой нижней строке "Обзор класса" говорят

Каждый экземпляр HttpURLConnection может использоваться для одного запрос/ответ.

Связи Keep-Alive работают на другом уровне, см. документы disconnect: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()

В отличие от других реализаций Java, это не обязательно будет закрыто которые могут быть повторно использованы. Вы можете отключить все соединения повторное использование, установив для свойства http.keepAlive system значение false до выдавая любые HTTP-запросы.

Итак, вы всегда должны использовать новое соединение HttpURLConnection и разрешить повторному использованию пула сокетов.

По-видимому, были ошибки с keep-alive соединениями pre-Froyo (2.2), поэтому рекомендуется отключать keep-alive на этих старых устройствах.

В моем случае EOFException был вызван тем, что мой сервер не отправил полный ответ, см. подробности здесь: fooobar.com/questions/160558/...

Ответ 6

Вы можете использовать этот метод для выбора данных с сервера, тогда вы преобразуете вставку в строку, а затем можете анализировать для дальнейшего использования.

  public static InputStream getUrlData(final String url)
        throws URISyntaxException, ClientProtocolException, IOException {
    final DefaultHttpClient client = new DefaultHttpClient();
    final HttpGet method = new HttpGet(new URI(url));
    final HttpResponse res = client.execute(method);
    return res.getEntity().getContent();
    }

Ответ 7

Может быть, httpClient "имеет больше ошибок" и устарел, но эта проблема с JellyBean является showstopper. Я использую Ksoap2, поэтому я попробовал все предлагаемые ответы, которые мог.

  • System.setProperty("http.keepAlive", "false");
  • httpTransportSE.getServiceConnection().setRequestProperty("Connection", "close");
  • httpTransportSE.getServiceConnection().disconnect();

Ничего не получилось - моим решением было откат версии Ksoap2, которую я использую от 3.1.1 до 2.6.5. Используя 2.6.5, проблема существенно уменьшается. Все еще тестирование, но, возможно, даже решено.

Ответ 8

Я обнаружил, что повторная попытка подключения исправляет проблему, как показано здесь: fooobar.com/questions/160541/...

Убедитесь, что вы закрыли соединение до вашего рекурсивного вызова.

Кроме того, я добавил к соединению следующее, чтобы закрыть соединение, хотя я не уверен, что это помогает:

if (retries > 0) {
    connection.setRequestProperty("Connection", "close");
}

Ответ 9

Вам не следует пытаться повторно использовать один и тот же экземпляр HttpURLConnection. docs в самой нижней строке "Обзор класса" говорят

Каждый экземпляр HttpURLConnection может использоваться для одного запрос/ответ.

Связи Keep-Alive работают на другом уровне, см. документы disconnect: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()

В отличие от других реализаций Java, это не обязательно будет закрыто которые могут быть повторно использованы. Вы можете отключить все соединения повторное использование, установив для свойства http.keepAlive system значение false до выдавая любые HTTP-запросы.

Таким образом, вы всегда должны использовать новое соединение HttpURLConnection и разрешить повторному использованию пула сокетов. Возможно, возникли проблемы, если он пытается повторно использовать сокет, который был закрыт сервером, на что ответы на этот вопрос касаются: Android HttpUrlConnection EOFException

По-видимому, были ошибки с keep-alive соединениями pre-Froyo (2.2), поэтому рекомендуется отключать keep-alive на этих старых устройствах.

В моем случае EOFException был вызван тем, что мой сервер не отправил полный ответ, см. подробности здесь: fooobar.com/questions/160541/...

Ответ 10

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

Ответ 11

Попробуйте этот код: `

Метод Httppost:

    HttpParams httpParams = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
    HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);
    HttpClient client = new DefaultHttpClient(httpParams);
    HttpPost request = new HttpPost("put_url");
    request.setHeader("Content-Type", "application/xml");

    String file = resourceXml();


    StringEntity se = null;
    try {
        se = new StringEntity(file);
    } catch (UnsupportedEncodingException e1) {

        e1.printStackTrace();
    }

    se.setContentEncoding("UTF-8");
    se.setContentType("application/xml");
    request.setEntity(se);
    HttpResponse response = null;
    try {
        response = client.execute(request);
    } catch (ClientProtocolException e1) {

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

        e1.printStackTrace();
    }

    HttpEntity entity = response.getEntity();
    InputStream is = null;
    try {
        is = entity.getContent();
    } catch (IllegalStateException e) {

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

        e.printStackTrace();
    }
    String _response = convertStreamToString(is);

    Log.i(TAG, "Response:" + _response);
    // Check if server response is valid code
    int res_code = response.getStatusLine().getStatusCode();
    Log.i(TAG, "status_code" + res_code);
    try {
        is.close();
    } catch (IOException e) {

        e.printStackTrace();
    }

`

Ответ 12

для преобразования потока в строку: `

private static String convertStreamToString(InputStream is) {

    BufferedReader reader = new BufferedReader(new InputStreamReader(is),
            8192);
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append((line + "\n"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return sb.toString();

}`