15

Here's the question in simplest way.

I create a HTTPS connection to my server through proxy using HttpUrlConnection Object.

My proxy closes the connection but my code still tries to reuse the same connection. And so I get EOFException.

How do I handle such cases?

Sudarshan Bhat
  • 3,772
  • 2
  • 26
  • 53

12 Answers12

9

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");
Community
  • 1
  • 1
kturney
  • 1,337
  • 11
  • 6
  • that will close connection everytime and slows down network connection. :( I don't want to do that. – Sudarshan Bhat Sep 12 '12 at 10:49
  • I agree that reusing the connections would be better. Have you made sure that the InputStream you get from the connection is closed after being used? – kturney Sep 12 '12 at 23:09
  • If I close the input stream I will be releasing all the resources held by the stream including the underlying socket. So connection cannot be reused in that case. – Sudarshan Bhat Sep 13 '12 at 05:19
  • Sorry, I should have put disconnected the connection http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect() – kturney Sep 15 '12 at 02:16
  • I'm not clear on what you would like clarified, but since this answer Square has released their [OkHttp](http://square.github.io/okhttp) library. OkHttp handles many of the idiosyncrasies of HTTP/S on Android for you (and supports SPDY!). – kturney Sep 26 '13 at 19:10
  • Found that Samsung Galaxy S III isn't working with this fix. Samsung Galaxy Tab 3, as well as Nexus 10 and Nexus 4, all work though. I've had issues in the past with Galaxy S III acting differently, so not quite sure how to handle this... – DemonGyro May 21 '14 at 17:46
  • It doesn't work on Android Emulator, API 16 with a slow connection. I think, a problem is in server's settings, because no exception happens with a fast connection. – CoolMind Apr 13 '17 at 11:03
  • I met this problem on Android Emulator. I just turn off the proxy (in Android Studio settings), the problem goes away. While this may not be a fundamental solution. – Sanbrother Nov 18 '17 at 11:58
6

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
Grantland Chew
  • 2,620
  • 26
  • 26
4

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.

Almer
  • 1,139
  • 1
  • 12
  • 14
1

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

finally {
     urlConnection.disconnect();
   }
Ajay Kumar Meher
  • 1,932
  • 16
  • 24
0

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();
    }
Helal Khan
  • 867
  • 3
  • 10
  • 25
0

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.

Justus Romijn
  • 15,699
  • 5
  • 51
  • 63
Tim T
  • 361
  • 3
  • 7
0

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");
}
Community
  • 1
  • 1
DemonGyro
  • 483
  • 3
  • 11
0

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

Community
  • 1
  • 1
tangobravo
  • 898
  • 10
  • 24
0

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

Community
  • 1
  • 1
tangobravo
  • 898
  • 10
  • 24
0
  if (Build.VERSION.SDK != null
                        && Build.VERSION.SDK_INT > 13) {
                    con.setRequestProperty("Connection", "close");
                }
Ali Ziaee
  • 569
  • 5
  • 10
-1

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

`

SubbaReddy PolamReddy
  • 2,083
  • 2
  • 17
  • 23
-1

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

}`
SubbaReddy PolamReddy
  • 2,083
  • 2
  • 17
  • 23