Question

[Solved] Android Error: java.net.SocketException: Socket closed

I’m seeing this error come up in my crash logs hundreds of times a week but I have spent at this point several weeks trying to chase down the error without any success. I have been unable to reproduce it on any of my devices. Here’s the stack trace:

Posix.java:-2 in "libcore.io.Posix.recvfromBytes"
Posix.java:131 in "libcore.io.Posix.recvfrom"
BlockGuardOs.java:164 in "libcore.io.BlockGuardOs.recvfrom"
IoBridge.java:513 in "libcore.io.IoBridge.recvfrom"
PlainSocketImpl.java:489 in "java.net.PlainSocketImpl.read"
PlainSocketImpl.java:46 in "java.net.PlainSocketImpl.access$000"
PlainSocketImpl.java:241 in "java.net.PlainSocketImpl$PlainSocketInputStream.read"
AbstractSessionInputBuffer.java:103 in "org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer"
AbstractSessionInputBuffer.java:191 in "org.apache.http.impl.io.AbstractSessionInputBuffer.readLine"
DefaultResponseParser.java:82 in "org.apache.http.impl.conn.DefaultResponseParser.parseHead"
AbstractMessageParser.java:174 in "org.apache.http.impl.io.AbstractMessageParser.parse"
AbstractHttpClientConnection.java:180 in "org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader"
DefaultClientConnection.java:235 in "org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader"
AbstractClientConnAdapter.java:259 in "org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader"
HttpRequestExecutor.java:279 in "org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse"
HttpRequestExecutor.java:121 in "org.apache.http.protocol.HttpRequestExecutor.execute"
DefaultRequestDirector.java:428 in "org.apache.http.impl.client.DefaultRequestDirector.execute"
AbstractHttpClient.java:555 in "org.apache.http.impl.client.AbstractHttpClient.execute"
AbstractHttpClient.java:487 in "org.apache.http.impl.client.AbstractHttpClient.execute"
AbstractHttpClient.java:465 in "org.apache.http.impl.client.AbstractHttpClient.execute"
Utilities.java:484 in "com.myapp.android.Utilities$8.run"

Here’s the block of code where the error is coming from… the exact where the crash occurs is HttpResponse response = httpclient.execute(httppost);:

 public static HttpPost postData(String URL, final List<NameValuePair> params, final Handler handler) {
        // Create a new HttpClient and Post Header
        //android.util.Log.d("Utilities", "Called postData");
        final HttpClient httpclient = new DefaultHttpClient();
        //httpclient.
        final HttpPost httppost = new HttpPost(URL);
        final Message msg = new Message();
        final Bundle dataBundle = new Bundle();
        final ByteArrayOutputStream out = new ByteArrayOutputStream();

        new Thread(){
            @Override
            public void run(){
                String error = "";
                String data = "";
                try {
                    httppost.setEntity(new UrlEncodedFormEntity(params));
                    HttpResponse response = httpclient.execute(httppost);
                    StatusLine statusLine = response.getStatusLine();
                    if(statusLine.getStatusCode() == HttpStatus.SC_OK){
                        response.getEntity().writeTo(out);
                        out.close();
                        data = out.toString();
                    } else{
                        error = EntityUtils.toString(response.getEntity());
                    }
                } catch (ClientProtocolException e) {
                    AirbrakeNotifier.notify(e);
                    error = e.toString();
                } catch (IOException e) {
                    AirbrakeNotifier.notify(e);
                    error = e.toString();
                } catch (Exception ex) {
                    AirbrakeNotifier.notify(ex);
                    error = ex.toString();
                }
                dataBundle.putString("error", error);
                dataBundle.putString("data", data);
                msg.setData(dataBundle);
                handler.dispatchMessage(msg);
            }
        }.start();
        return httppost;
    }

Any help on finally figuring this one out is greatly appreciated!

Enquirer: D-Nice

||

Solution #1:

In my opinion, the culprit of this problem is not your app, but the remote side (i.e., the HTTP server). The most probable thing is that the HTTP server is suddenly resetting the connection and this causes a SocketException in your app. In production environments, these things happen quite often. It might be caused by an overload of the HTTP server, some exceptional circumstance that might make the server close (HTTP request flood, or even an incremented number of requests when the remote server has run out of resources; the server could also run out of its local socket pool… reasons might be dozens).

If the proportion of these errors is low in comparison with the successful HTTP requests, I wouldn’t worry much, I’d just wrap that piece of code into a try { ... } catch (SocketException e) { ... } statement and show to the user a dialog telling them that the request has failed and they should retry.

What I would certainly do is try to determine the reason of this behavior: I’d try to match the time of one of these exceptions and try to dig into the HTTP server logs nearly to that time to try to determine the cause of this sudden disconnection (assuming you have access to that logs and other diagnostic tools). As I said before, it might be a silly thing or a bit more complex to debug, but I’d bet this is the problem.

Respondent: D-Nice

Solution #2:

A “java.net.SocketException: Socket closed” exception can happen in various situations. Either the server side closed the connection like nKn suggested, or the client side (your app) closed the connection. Even if you are not aware of doing it, there may be some less obvious code that may lead to closing the socket, like Thread.interrupt() or ExecutorService.shutdownNow().

If on the other hand it actually happens on the server side, I would advise that you implement retries – 3 tries are common practice and usually sufficient.

Respondent: nKn

Solution #3:

You are currently accepting whatever defaults the client lib is config’d with. Maybe you want to take more control of your Httpclient lib particularly regarding the socket TIMEOUT setting. Dont wait for the server to do something unexpected. Set a shorter timeout than the default and control the errors in a way that will make some sense to your users “Try later msg”….

If u are using default android httpclient you may want to look at alternatives that keep up with the newer Apache client releases…

https://hc.apache.org/httpcomponents-client-4.3.x/android-port.html

https://code.google.com/p/httpclientandroidlib/

general background async client

and note that with either of these you can take into account ( on Wifi ) OR ( on 4G ) that you can dial in detailed timeout profiles where you control the timeouts with code like below:

public void create(int method, final String url, final String data) {
    this.method = method;
    this.url = url;     
    this.data = data;
    if(method == GET){
        this.config = RequestConfig.custom()
            .setConnectTimeout(6 * 1000)
            .setConnectionRequestTimeout(30 * 1000)
            .setSocketTimeout(30 * 1000)                
            .build();
    } else{
        this.config = RequestConfig.custom()
                .setConnectTimeout(6 * 1000)
                .setConnectionRequestTimeout(30 * 1000)
                .setSocketTimeout(60 * 1000)                
                .build();           
    }
    this.context = HttpClientContext.create(); 

using handlers and callbacks to the UI so you can show any alert dialog you want

in runnable where you have the ‘..client.exec(request$Type)’

        if(httprc < HttpStatus.SC_METHOD_NOT_ALLOWED){

            Log.d(TAG, "entityTYP " +response.getEntity().getClass().getName());
            processEntity(response.getEntity());
            response.close();
        }else{
            Log.d(TAG, "ERR httprc " +httprc);
            throw new IOException("httprc " +httprc +" on " +method);
            }                               
        this.context.getConnection().close();
} catch (Exception e) {  // this will catch your 'socketException'
   // catch and use the looper to direct to the desired UI thread handle
    handler0.sendMessage(Message.obtain(handler,
            HttpConnection.DID_ERROR, e.getMessage()));
}

back on the UI thread you control the alert for as many diff handlers as u need….

           handler0 = new Handler() {
               public void handleMessage(Message message) {
                 switch (message.what) {
                 case HttpConnection.DID_START: {
                   break;
                 }
                 case HttpConnection.DID_SUCCEED: {                                          
                   break;
                 }
                 case HttpConnection.DID_ERROR: {
                       toggleSpin(false);
                       cleanup();
                    //have access to orig message.obj here as well
                       Toast.makeText(Speech_API_Activity.this, getResources().getString(R.string.heroku_msg_mux),
                            Toast.LENGTH_SHORT).show();
                       break;
                     }

If necessary, you may establish diff timeout profiles by domain. It takes time to learn all the builder stuff and config stuff with these other 2 httpclient packages but , it may be worth the time because you can set it up to do anything you want and you have total control of exceptions and of what you want to route back to the UI.

Respondent: Christian Esken

Solution #4:

  • What are you doing with HttpPost object returned from method
    postData(…) ? That may be one of the cause to consider. Note there
    are two threads, one main thread and another one that you spawn
    above.

  • In finally block you need to close resources like httpClient and
    response as well as completely empty out response inputstream. See examples for reference.

  • Explicitly set charset on UrlEncodedFormEntity, may be to UTF-8

Respondent: Robert Rowntree

Solution #5:

try to use this

public static String WebserviceResponseHandle(String url,
        List<NameValuePair> namvaluePair) {
    String result = null;
    try {
        HttpParams httpParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
        HttpConnectionParams.setSoTimeout(httpParams, 10000);
        HttpClient client = new DefaultHttpClient(httpParams);
        HttpPost httppost = new HttpPost(url);
        httppost.setEntity(new UrlEncodedFormEntity(namvaluePair));
        HttpResponse response = client.execute(httppost);
        HttpEntity entity = response.getEntity();

        // If the response does not enclose an entity, there is no need
        if (entity != null) {
            InputStream instream = entity.getContent();
            result = convertStreamToString(instream);

        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}


    private static String convertStreamToString(InputStream is) {
    /*
     * To convert the InputStream to String we use the
     * BufferedReader.readLine() method. We iterate until the BufferedReader
     * return null which means there's no more data to read. Each line will
     * appended to a StringBuilder and returned as String.
     */
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

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

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Most Popular

To Top
India and Pakistan’s steroid-soaked rhetoric over Kashmir will come back to haunt them both clenbuterol australia bossier man pleads guilty for leadership role in anabolic steriod distribution conspiracy