Ошибка Android: java.net.SocketException: сокет закрыт

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

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" 

Вот блок кода, откуда исходит ошибка … точное место возникновения сбоя – 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; } 

Любая помощь при окончательном вычислении этого результата очень ценится!

На мой взгляд, виновником этой проблемы является не ваше приложение, а удаленная сторона (т. Е. HTTP-сервер). Наиболее вероятно, что HTTP-сервер внезапно SocketException соединение, и это вызывает SocketException в вашем приложении. В производственных условиях это происходит довольно часто. Это может быть вызвано перегрузкой HTTP-сервера, некоторыми исключительными обстоятельствами, которые могут привести к закрытию сервера (нагрузка HTTP-запроса или даже увеличение количества запросов, когда на удаленном сервере закончились ресурсы, на сервере также может закончиться Его локальный пул сокетов … причины могут быть десятки).

Если доля этих ошибок невысока по сравнению с успешными HTTP-запросами, я бы не стал волноваться, я бы просто обернул этот фрагмент кода в try { ... } catch (SocketException e) { ... } И показать пользователю диалоговое окно, в котором сообщается, что запрос не выполнен, и они должны повторить попытку.

То, что я, безусловно, сделаю, это попытаться определить причину такого поведения: я постараюсь сопоставить время одного из этих исключений и попытаться в течение долгого времени копаться в журналах HTTP-сервера, чтобы попытаться определить причину этого внезапного Отключение (при условии, что у вас есть доступ к этим журналам и другим диагностическим инструментам). Как я уже говорил, это может быть глупо или немного сложнее отладить, но я бы сказал, что это проблема.

Исключение «java.net.SocketException: Socket closed» может происходить в разных ситуациях. Либо серверная сторона закрыла соединение, как nKn, либо клиентская сторона (ваше приложение) закрыла соединение. Даже если вы не знаете об этом, может быть несколько менее очевидный код, который может привести к закрытию сокета, например Thread.interrupt () или ExecutorService.shutdownNow ().

Если, с другой стороны, это действительно происходит на стороне сервера, я бы посоветовал вам внедрять повторные попытки – 3 попытки являются обычной практикой и обычно достаточны.

В настоящее время вы принимаете любые настройки по умолчанию, с которыми сконфигурирована клиентская библиотека. Возможно, вы хотите больше контролировать свой Httpclient lib, особенно в отношении установки TIMEOUT сокета. Не ожидайте, что сервер сделает что-то неожиданное. Установите более короткий тайм-аут, чем значение по умолчанию, и контролируйте ошибки таким образом, который будет иметь смысл для ваших пользователей. «Попробуйте позже msg» ….

Если вы используете по умолчанию android httpclient, вы можете захотеть взглянуть на альтернативы, которые не отстают от новых версий Apache-клиентов …

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

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

Общий фоновый асинхронный клиент

И обратите внимание, что с любым из них вы можете принять во внимание (по Wi-Fi) ИЛИ (на 4G), что вы можете набирать подробные профили тайм-аута, где вы контролируете таймауты с кодом, как показано ниже:

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

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

В runnable, где у вас есть «..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())); } 

Назад в поток пользовательского интерфейса вы управляете предупреждением для как можно большего количества обработчиков diff.

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

При необходимости вы можете установить профили тайм-аута разности по доменам. Требуется время, чтобы изучить все материалы строителя и файлы конфигурации с этими двумя другими пакетами httpclient, но, возможно, стоит потратить время, потому что вы можете настроить его на все, что хотите, и у вас есть полный контроль над исключениями и того, что вы хотите Вернуться к пользовательскому интерфейсу.

  • Что вы делаете с объектом HttpPost, возвращаемым из метода postData (…)? Это может быть одной из причин для рассмотрения. Обратите внимание, что есть два потока, один основной поток и другой, который вы создаете выше.

  • В блоке finally вам нужно закрыть ресурсы, такие как httpClient и
    А также полностью очистить входной поток ответов. См. Примеры для справки.

  • Явно установить кодировку на UrlEncodedFormEntity, может быть в UTF-8

Попытайтесь использовать это

 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 + "\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } 
Intereting Posts