Android IOException与http。。。但它仍然有效

Android IOException与http。。。但它仍然有效,android,httpclient,Android,Httpclient,我正在使用httpclient与web服务器通信,但偶尔会出现IOException,但奇怪的是,该命令仍然会发送到web服务器。事实上,我甚至通常会从服务器返回一个有效的数据响应以及IOException。我应该如何对待这些例外 这是我的代码,以防我做错了什么: DefaultHttpClient client = new DefaultHttpClient(); CookieSyncManager.getInstance().startSync(); HttpContext localCon

我正在使用httpclient与web服务器通信,但偶尔会出现IOException,但奇怪的是,该命令仍然会发送到web服务器。事实上,我甚至通常会从服务器返回一个有效的数据响应以及IOException。我应该如何对待这些例外

这是我的代码,以防我做错了什么:

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)
记住,这里的问题是我捕获了异常,但代码仍然有效,我可以看到服务器接收到命令,甚至从服务器得到响应

我做了一些wireshark嗅探,一个好的会话和一个坏的会话看起来几乎相同,唯一的例外是最终响应返回电话所需的时间。由于异常实际上是一个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???听起来有点危险……

我想问题出在这一行的插座超时:

HttpConnectionParams.setSoTimeout(httpParams, 5000);
如果我们查看HttpClient文档的这一部分:

例如,如果HTTP服务器成功接收和处理请求,生成响应并将状态代码发送回客户端,则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*/
}

由于错误发生在execute.getEntity()行,因此我认为没有必要在该行之后编写代码。无论如何,谢谢你的帮助。代码的其余部分已经添加。我希望有帮助!:)大家都去哪了?我一直在研究这个问题,我不知道应该做些什么来避免出现这个错误。也许我做错了?好吧,我将把这件事留着,希望有人会来看看,并有一个好的答案。同时,我已经在我的应用程序中禁用了此错误的报告。也许我发现了一个安卓bug???