Android HttpURLConnection throwing EOFException

这一生的挚爱 提交于 2019-11-29 01:28:25
kturney

I'd recommend disabling the http.keepalive system property. The performance section of the documentation indicates that socket connections will be reused when possible. It sounds like it is trying to reuse the connection, but the proxy has already closed it. On this post, Darrell also indicates that changing the system property solved his problem.

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

Turns out they've fixed this issue in Android on Jan 8th [1]. The fix basically marks the old connection as recycled and internally retries the request.

To fix this for now, I would suggest retrying requests if an EOFException is encountered with a retry limit to prevent stackoverlows.

  1. https://android.googlesource.com/platform/libcore/+/19aa40c81c48ff98ccc7272f2a3c41479b806376

I had this problem with normal HTTP connections as well. The first request went OK, the second failed with an EOFException.

Eventuelly I fixed it by removing...

urlConnection.setChunkedStreamingMode(0);

...from the HttpUrlConnection.

I could be that the webserver I'm calling can't handle chuncked data well. Don't know.

If you don't want to reuse the connection then release it.

finally {
     urlConnection.disconnect();
   }

You can use this method to pick data from server then you convert the inputs trim to string then you can parse for further use.`

  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();
    }
Tim T

Maybe httpClient "has more bugs" and is deprecated, but this problem with JellyBean is a showstopper. I am using Ksoap2 so I tried all the suggested answers that I could.

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

Nothing worked - my solution was to rollback the version of Ksoap2 I'm using from 3.1.1 to 2.6.5. Using 2.6.5 the problem is substantially reduced. Still testing but maybe even solved.

DemonGyro

I found that retrying the connection fixes the issue as seen here: https://stackoverflow.com/a/20302767/2520390

Make sure you close off the connection before your recursive call.

Also, I added the following to the connection to close the connection, though I'm not sure if it helps:

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

You shouldn't be attempting to reuse the same HttpURLConnection instance. The docs in the very bottom line of the "Class Overview" say

Each instance of HttpURLConnection may be used for one request/response pair.

Keep-Alive connections work at a different level, see the disconnect docs: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()

Unlike other Java implementations, this will not necessarily close socket connections that can be reused. You can disable all connection reuse by setting the http.keepAlive system property to false before issuing any HTTP requests.

So you should always use a fresh HttpURLConnection and let the socket pool handle re-use.

There were apparently bugs with keep-alive connections pre-Froyo (2.2) so it is recommended to disable keep-alive on those old devices.

In my case the EOFException was caused by my server not sending a full response, see the details here: https://stackoverflow.com/a/27845172/2335025

tangobravo

You shouldn't be attempting to reuse the same HttpURLConnection instance. The docs in the very bottom line of the "Class Overview" say

Each instance of HttpURLConnection may be used for one request/response pair.

Keep-Alive connections work at a different level, see the disconnect docs: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()

Unlike other Java implementations, this will not necessarily close socket connections that can be reused. You can disable all connection reuse by setting the http.keepAlive system property to false before issuing any HTTP requests.

So you should always use a fresh HttpURLConnection and let the socket pool handle re-use. There are perhaps issues if it tries to reuse a socket that has been closed by the server, which the answers to this question deal with: Android HttpUrlConnection EOFException

There were apparently bugs with keep-alive connections pre-Froyo (2.2) so it is recommended to disable keep-alive on those old devices.

In my case the EOFException was caused by my server not sending a full response, see the details here: https://stackoverflow.com/a/27845939/2335025

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

Try this code:`

Httppost method:

    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();
    }

`

to convert stream to string:`

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();

}`
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!