Android IOException с http ... но все равно работает - PullRequest
0 голосов
/ 09 февраля 2012

Я использую httpclient для общения с веб-сервером, но иногда получаю IOException, но странно то, что команда все равно добирается до веб-сервера.На самом деле, я даже обычно получаю верный ответ на данные с сервера вместе с IOException.Как мне обращаться с IOExceptions?

Вот мой код на случай, если я что-то не так делаю:

DefaultHttpClient client = new DefaultHttpClient();
CookieSyncManager.getInstance().startSync();
HttpContext localContext = new BasicHttpContext();

String password = db.getWebPassword();
String username = db.getWebUsername();

HttpGet httpGet = new HttpGet(url);

final HttpParams httpParams = client.getParams();

// try playing with the timesouts, but I don't think I know what I am doing...
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);

Integer responseCode = 0;
try 
{
    HttpResponse execute;
    UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
    client.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), creds);
    execute = client.execute(httpGet);
    HttpEntity entity = execute.getEntity(); // often catches an IOException here     
    Log.d(MY_DEBUG_TAG, "Execute complete: " + entity.toString());
    responseCode = execute.getStatusLine().getStatusCode();
    Log.d(MY_DEBUG_TAG, "Response Code: " + responseCode);
    if (responseCode == 401)
    {
         response = "ERROR";
     Toast.ShowToast("Username/Password error.", pa);
    }

    InputStream content = execute.getEntity().getContent();

    Log.d(MY_DEBUG_TAG, "Reading response");
    BufferedReader buffer = new BufferedReader(
              new InputStreamReader(content));
    String s = "";
    while ((s = buffer.readLine()) != null) 
    {
         response += s;
    }
    // remove all html if possible
    response = android.text.Html.fromHtml(response).toString();
    Log.d(MY_DEBUG_TAG, "Response = " + response);
}
catch (ClientProtocolException e) 
{
     Log.e(MY_ERROR_TAG, "ClientProtocolException: " + e.getMessage());
     Toast.ShowToast("Error connecting to server.", pa);
}
catch (IOException e)
{
       Log.e(MY_ERROR_TAG, "IOException: " + e.getMessage());
     Toast.ShowToast("Error connecting to server.", pa);
}

Трассировка стека добавлена ​​согласно запросу:

java.net.SocketTimeoutException
    at org.apache.harmony.luni.net.PlainSocketImpl.read(PlainSocketImpl.java:564)
    at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:88)
    at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
    at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:191)
    at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:82)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:174)
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:179)
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:235)
    at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:259)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:279)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:121)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:410)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
    at com.PowerHomeConnectorForAndroid.Network$GetHttpData.doInBackground(Network.java:215)
    at com.PowerHomeConnectorForAndroid.Network$GetHttpData.doInBackground(Network.java:1)
    at android.os.AsyncTask$2.call(AsyncTask.java:185)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
    at java.lang.Thread.run(Thread.java:1096)

Помните, проблема здесь в том, что я перехватываю исключение, но код все еще работает, я вижу, что сервер получает команду, и я даже получаю ответ от сервера.и хороший сеанс и плохой сеанс выглядят почти одинаково, за исключением того, что количество времени, необходимое для получения окончательного ответа на телефон, возвращается.Поскольку исключение на самом деле является SocketTimeoutException, я полагаю, что это имеет смысл, но реальность такова, что ответ действительно возвращает его, и телефон принимает его как часть одного сеанса, так что же на самом деле происходит?Было ли исключение или нет?

Вот захват Wireshark (извините за прокрутку влево-вправо) Первый захват плохой сеанс, а второй хороший сеанс.

      IOException                                                                                                                                                           x     Good                              
1     http-alt     0             70.165.69.220     192.168.1.110     TCP     66     20180 > http-alt [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1                 x     31     http-alt     0            70.165.69.220     192.168.1.110     TCP     66     52220 > http-alt [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
2     20180        0.000039      192.168.1.110     70.165.69.220     TCP     66     http-alt > 20180 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1      x     32     52220        0.000043     192.168.1.110     70.165.69.220     TCP     66     http-alt > 52220 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
3     http-alt     0.05784       70.165.69.220     192.168.1.110     TCP     60     20180 > http-alt [ACK] Seq=1 Ack=1 Win=65536 Len=0                                      x     33     http-alt     0.22131      70.165.69.220     192.168.1.110     TCP     60     52220 > http-alt [ACK] Seq=1 Ack=1 Win=65536 Len=0
4     http-alt     0.153949      70.165.69.220     192.168.1.110     HTTP   196     GET /ph-cgi/clogin HTTP/1.1                                                             x     34     http-alt     0.350917     70.165.69.220     192.168.1.110     HTTP   196     GET /ph-cgi/clogin HTTP/1.1 
5     20180        0.161902      192.168.1.110     70.165.69.220     HTTP  2967     HTTP/1.0 200 OK  (text/html)                                                            x     35     52220        0.3841       192.168.1.110     70.165.69.220     HTTP  2967     HTTP/1.0 200 OK  (text/html)
6     20180        0.161992      192.168.1.110     70.165.69.220     TCP     54     http-alt > 20180 [FIN, ACK] Seq=2914 Ack=143 Win=65536 Len=0                            x     36     52220        0.38419      192.168.1.110     70.165.69.220     TCP     54     http-alt > 52220 [FIN, ACK] Seq=2914 Ack=143 Win=65536 Len=0
7     http-alt     0.209671      70.165.69.220     192.168.1.110     TCP     60     20180 > http-alt [ACK] Seq=143 Ack=1461 Win=65536 Len=0                                 x     37     http-alt     0.614323     70.165.69.220     192.168.1.110     TCP     60     52220 > http-alt [ACK] Seq=143 Ack=1461 Win=65536 Len=0
8     http-alt     0.253024      70.165.69.220     192.168.1.110     TCP     60     20180 > http-alt [ACK] Seq=143 Ack=2915 Win=64000 Len=0                                 x     38     http-alt     0.614456     70.165.69.220     192.168.1.110     TCP     60     52220 > http-alt [ACK] Seq=143 Ack=2915 Win=64000 Len=0
9     http-alt     0.373148      70.165.69.220     192.168.1.110     TCP     60     20180 > http-alt [FIN, ACK] Seq=143 Ack=2915 Win=64000 Len=0                            x     39     http-alt     0.746923     70.165.69.220     192.168.1.110     TCP     60     52220 > http-alt [FIN, ACK] Seq=143 Ack=2915 Win=64000 Len=0
10    20180        0.373172      192.168.1.110     70.165.69.220     TCP     54     http-alt > 20180 [ACK] Seq=2915 Ack=144 Win=65536 Len=0                                 x     40     52220        0.746944     192.168.1.110     70.165.69.220     TCP     54     http-alt > 52220 [ACK] Seq=2915 Ack=144 Win=65536 Len=0
11    http-alt     0.38402       70.165.69.220     192.168.1.110     TCP     66     53091 > http-alt [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1                 x     41     http-alt     0.762482     70.165.69.220     192.168.1.110     TCP     66     64314 > http-alt [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
12    53091        0.384069      192.168.1.110     70.165.69.220     TCP     66     http-alt > 53091 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1      x     42     64314        0.762517     192.168.1.110     70.165.69.220     TCP     66     http-alt > 64314 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
13    http-alt     0.425956      70.165.69.220     192.168.1.110     TCP     60     53091 > http-alt [ACK] Seq=1 Ack=1 Win=65536 Len=0                                      x     43     http-alt     1.015043     70.165.69.220     192.168.1.110     TCP     60     64314 > http-alt [ACK] Seq=1 Ack=1 Win=65536 Len=0
14    http-alt     0.511349      70.165.69.220     192.168.1.110     TCP    349     [TCP segment of a reassembled PDU]                                                      x     44     http-alt     1.064351     70.165.69.220     192.168.1.110     TCP    349     [TCP segment of a reassembled PDU]
15    53091        0.704456      192.168.1.110     70.165.69.220     TCP     54     http-alt > 53091 [ACK] Seq=1 Ack=296 Win=65536 Len=0                                    x     45     64314        1.263922     192.168.1.110     70.165.69.220     TCP     54     http-alt > 64314 [ACK] Seq=1 Ack=296 Win=65536 Len=0
16    http-alt     2.562688      70.165.69.220     192.168.1.110     HTTP    99     POST /ph-cgi/cauth HTTP/1.1  (application/x-www-form-urlencoded)                        x     46     http-alt     3.088689     70.165.69.220     192.168.1.110     HTTP    99     POST /ph-cgi/cauth HTTP/1.1  (application/x-www-form-urlencoded)
17    53091        2.567888      192.168.1.110     70.165.69.220     HTTP   355     HTTP/1.0 200 OK  (text/html)                                                            x     47     64314        3.093318     192.168.1.110     70.165.69.220     HTTP   355     HTTP/1.0 200 OK  (text/html)
18    53091        2.568447      192.168.1.110     70.165.69.220     TCP     54     http-alt > 53091 [FIN, ACK] Seq=302 Ack=341 Win=65536 Len=0                             x     48     64314        3.093858     192.168.1.110     70.165.69.220     TCP     54     http-alt > 64314 [FIN, ACK] Seq=302 Ack=341 Win=65536 Len=0
19    http-alt     2.612071      70.165.69.220     192.168.1.110     TCP     60     53091 > http-alt [ACK] Seq=341 Ack=303 Win=65280 Len=0                                  x     49     http-alt     3.313276     70.165.69.220     192.168.1.110     TCP     60     64314 > http-alt [ACK] Seq=341 Ack=303 Win=65280 Len=0
20    http-alt     2.665338      70.165.69.220     192.168.1.110     TCP     66     34654 > http-alt [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1                 x     50     http-alt     3.410808     70.165.69.220     192.168.1.110     TCP     66     33703 > http-alt [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
21    34654        2.665385      192.168.1.110     70.165.69.220     TCP     66     http-alt > 34654 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1      x     51     33703        3.410851     192.168.1.110     70.165.69.220     TCP     66     http-alt > 33703 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
22    http-alt     2.665487      70.165.69.220     192.168.1.110     TCP     60     53091 > http-alt [FIN, ACK] Seq=341 Ack=303 Win=65280 Len=0                             x     52     http-alt     3.41086      70.165.69.220     192.168.1.110     TCP     60     64314 > http-alt [FIN, ACK] Seq=341 Ack=303 Win=65280 Len=0
23    53091        2.6655        192.168.1.110     70.165.69.220     TCP     54     http-alt > 53091 [ACK] Seq=303 Ack=342 Win=65536 Len=0                                  x     53     64314        3.41087      192.168.1.110     70.165.69.220     TCP     54     http-alt > 64314 [ACK] Seq=303 Ack=342 Win=65536 Len=0
24    http-alt     2.709857      70.165.69.220     192.168.1.110     TCP     60     34654 > http-alt [ACK] Seq=1 Ack=1 Win=65536 Len=0                                      x     54     http-alt     3.715974     70.165.69.220     192.168.1.110     TCP     60     33703 > http-alt [ACK] Seq=1 Ack=1 Win=65536 Len=0
25    http-alt     2.916243      70.165.69.220     192.168.1.110     HTTP   308     GET /ph-cgi/eval?formula=ph_macro%28%27TESTING%27%29 HTTP/1.1                           x     55     http-alt     3.830971     70.165.69.220     192.168.1.110     HTTP   308     GET /ph-cgi/eval?formula=ph_macro%28%27TESTING%27%29 HTTP/1.1 
26    34654        3.114457      192.168.1.110     70.165.69.220     TCP     54     http-alt > 34654 [ACK] Seq=1 Ack=255 Win=65536 Len=0                                    x     56     33703        3.858623     192.168.1.110     70.165.69.220     HTTP   153     HTTP/1.0 200 OK  (text/html)
27    http-alt     11.023287     70.165.69.220     192.168.1.110     TCP     60     34654 > http-alt [FIN, ACK] Seq=255 Ack=1 Win=65536 Len=0                               x     57     33703        3.858729     192.168.1.110     70.165.69.220     TCP     54     http-alt > 33703 [FIN, ACK] Seq=100 Ack=255 Win=65536 Len=0
28    34654        11.023305     192.168.1.110     70.165.69.220     TCP     54     http-alt > 34654 [ACK] Seq=1 Ack=256 Win=65536 Len=0                                    x     58     http-alt     4.114668     70.165.69.220     192.168.1.110     TCP     60     33703 > http-alt [ACK] Seq=255 Ack=101 Win=65536 Len=0
29    34654        34.882577     192.168.1.110     70.165.69.220     TCP     54     http-alt > 34654 [FIN, ACK] Seq=1 Ack=256 Win=65536 Len=0                               x     59     http-alt     4.153392     70.165.69.220     192.168.1.110     TCP     60     33703 > http-alt [FIN, ACK] Seq=255 Ack=101 Win=65536 Len=0
30    http-alt     34.926041     70.165.69.220     192.168.1.110     TCP     60     34654 > http-alt [ACK] Seq=256 Ack=2 Win=65536 Len=0                                    x     60     33703        4.153402     192.168.1.110     70.165.69.220     TCP     54     http-alt > 33703 [ACK] Seq=101 Ack=256 Win=65536 Len=0

Так, возможно, я должен просто игнорировать исключение SocketTimeoutException ???Звучит как-то опасно ....

1 Ответ

2 голосов
/ 31 января 2013

Я думаю, что проблема в тайм-ауте сокета у вас в этой строке:

HttpConnectionParams.setSoTimeout(httpParams, 5000);

Если мы посмотрим на эту часть документации HttpClient: http://hc.apache.org/httpclient-legacy/exception-handling.html

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

Тот факт, что сервер получает запрос и отправляет ответ, может быть тем, что описывается в документации. Решением было бы увеличить SoTimeout или повторить запрос:

HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler(){
        @Override
        public boolean retryRequest(IOException exception,
                int executionCount, HttpContext context) {

            if (executionCount >= 5) {
                Log.e("Retry Limit", "Retry #: " + executionCount);
                return false;
            }

            if(exception instanceof java.net.SocketTimeoutException){
                Log.e("(SocketTimeoutException)", "Retry #: " + executionCount);
                return true;
            }
            if(exception instanceof java.net.SocketException){
                Log.e("(SocketException)", "Retry #: " + executionCount);
                return true;
            }
            if(exception instanceof ObjectStreamException){
                Log.e("(ObjectStreamException)", "Retry #: " + executionCount);
                return true;
            }
            if(exception instanceof ProtocolException){
                Log.e("(ProtocolException)", "Retry #: " + executionCount);
                return true;
            }
            if(exception instanceof SSLException){
                Log.e("(SSLException)", "Retry #: " + executionCount);
                return true;
            }
            if(exception instanceof SyncFailedException){
                Log.e("(SyncFailedException)", "Retry #: " + executionCount);
                return true;
            }
            if(exception instanceof UTFDataFormatException){
                Log.e("(UTFDataFormatException)", "Retry #: " + executionCount);
                return true;
            }
            return false;
        }
    };
    client.setHttpRequestRetryHandler(retryHandler);

Это поймает SocketTimeOut,SocketException и т. Д. Но если вы получите IOException, вы можете повторить запрос вручную:

catch (IOException e)
{
    SystemClock.sleep(1500);
       Log.e(MY_ERROR_TAG, "IOException: " + e.getMessage());
     Toast.ShowToast("Error connecting to server.", pa);
    /*RETRY THE REQUEST MANUALLY*/
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...