Android HttpClient在执行期间发送第一个数据包

时间:2013-02-06 21:07:39

标签: java android multithreading apache-commons-httpclient

在我的应用程序中尝试使用HttpClient时,我遇到了一个相当令人困惑的难题。看似随意,HttpClient.execute(HttpRequest)永远不会回来!好吧......如果我使用HttpConnectionParams.setConnectionTimeout(HttpParams, int)设置超时,它将抛出超时异常。否则我的后台线程将永远挂起。

我在阳光下尝试了一切来解决这个问题,但无济于事。在没有其他选择的情况下,我抓住了问题的数据包捕获并发现了令人惊讶的事情! (或者也许并不那么令人惊讶,我不是网络人士)

成功通话:

 905 75.286537   192.168.20.163        192.168.20.171        TCP      74     34340 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSval=411399 TSecr=0 WS=16
 906 75.286634   192.168.20.171        192.168.20.163        TCP      74     http > 34340 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1260 WS=256 SACK_PERM=1 TSval=2129684 TSecr=411399
 919 78.280782   192.168.20.163        192.168.20.171        TCP      74     34340 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSval=411783 TSecr=0 WS=16
 920 78.286704   192.168.20.171        192.168.20.163        TCP      74     http > 34340 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1260 WS=256 SACK_PERM=1 TSval=2129984 TSecr=411399
 955 84.280710   192.168.20.163        192.168.20.171        TCP      74     34340 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSval=412551 TSecr=0 WS=16
 956 84.287958   192.168.20.171        192.168.20.163        TCP      70     http > 34340 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1260 SACK_PERM=1 TSval=2130584 TSecr=411399
 957 84.288332   192.168.20.163        192.168.20.171        TCP      66     34340 > http [ACK] Seq=1 Ack=1 Win=93440 Len=0 TSval=412551 TSecr=2130584
 959 84.648812   192.168.20.163        192.168.20.171        TCP      294    [TCP segment of a reassembled PDU]
 960 84.649333   192.168.20.163        192.168.20.171        HTTP     411    POST /xxxxx.Service/xxxxx.asmx/GetReservations HTTP/1.1  (application/json)
 961 84.649368   192.168.20.171        192.168.20.163        TCP      66     http > 34340 [ACK] Seq=1 Ack=574 Win=16630272 Len=0 TSval=2130620 TSecr=412598
 962 84.656518   192.168.20.171        192.168.20.163        TCP      1314   [TCP segment of a reassembled PDU]
 963 84.656560   192.168.20.171        192.168.20.163        HTTP     580    HTTP/1.1 200 OK  (application/json)
 964 84.657192   192.168.20.163        192.168.20.171        TCP      66     34340 > http [ACK] Seq=574 Ack=1249 Win=119808 Len=0 TSval=412599 TSecr=2130621
 965 84.686906   192.168.20.163        192.168.20.171        TCP      66     34340 > http [ACK] Seq=574 Ack=1764 Win=159744 Len=0 TSval=412603 TSecr=2130621
 968 85.187509   192.168.20.163        192.168.20.171        TCP      66     34340 > http [FIN, ACK] Seq=574 Ack=1764 Win=159744 Len=0 TSval=412667 TSecr=2130621
 969 85.187567   192.168.20.171        192.168.20.163        TCP      66     http > 34340 [ACK] Seq=1764 Ack=575 Win=16630272 Len=0 TSval=2130674 TSecr=412667

通话失败:

2653 195.296440  192.168.20.163        192.168.20.171        TCP      74     60962 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSval=426761 TSecr=0 WS=16
2656 195.296894  192.168.20.171        192.168.20.163        TCP      74     http > 60962 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1260 WS=256 SACK_PERM=1 TSval=2141685 TSecr=426761
2658 195.297191  192.168.20.163        192.168.20.171        TCP      66     60962 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0 TSval=426761 TSecr=2141685
2659 195.669276  192.168.20.163        192.168.20.171        TCP      294    [TCP segment of a reassembled PDU]
2660 195.669749  192.168.20.163        192.168.20.171        HTTP     411    POST /xxxxx.Service/xxxxx.asmx/GetReservations HTTP/1.1  (application/json)
2661 195.669783  192.168.20.171        192.168.20.163        TCP      66     http > 60962 [ACK] Seq=1 Ack=574 Win=66048 Len=0 TSval=2141722 TSecr=426809
2662 195.670095  192.168.20.163        192.168.20.171        TCP      60     60962 > http [RST] Seq=574 Win=0 Len=0
2802 215.154316  192.168.20.163        192.168.20.171        TCP      74     48450 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSval=429303 TSecr=0 WS=16
2803 215.154397  192.168.20.171        192.168.20.163        TCP      74     http > 48450 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1260 WS=256 SACK_PERM=1 TSval=2143671 TSecr=429303
2804 215.154704  192.168.20.163        192.168.20.171        TCP      60     48450 > http [RST] Seq=1 Win=0 Len=0
2807 215.716852  192.168.20.163        192.168.20.171        TCP      66     60962 > http [FIN, ACK] Seq=574 Ack=1 Win=5840 Len=0 TSval=429375 TSecr=2141685
2826 218.152321  192.168.20.163        192.168.20.171        TCP      74     48450 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSval=429687 TSecr=0 WS=16
2827 218.152387  192.168.20.171        192.168.20.163        TCP      74     [TCP Previous segment lost] http > 48450 [SYN, ACK] Seq=821395 Ack=1 Win=8192 Len=0 MSS=1260 WS=256 SACK_PERM=1 TSval=2143970 TSecr=429687
2828 218.152669  192.168.20.163        192.168.20.171        TCP      60     48450 > http [RST] Seq=1 Win=0 Len=0
2957 224.152259  192.168.20.163        192.168.20.171        TCP      74     48450 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSval=430455 TSecr=0 WS=16
2958 224.152379  192.168.20.171        192.168.20.163        TCP      74     [TCP Previous segment lost] http > 48450 [SYN, ACK] Seq=1936893 Ack=1 Win=8192 Len=0 MSS=1260 WS=256 SACK_PERM=1 TSval=2144570 TSecr=430455
2959 224.152722  192.168.20.163        192.168.20.171        TCP      60     48450 > http [RST] Seq=1 Win=0 Len=0
3032 230.130084  192.168.20.163        192.168.20.171        TCP      639    [TCP Retransmission] 60962 > http [FIN, PSH, ACK] Seq=1 Ack=1 Win=5840 Len=573 TSval=431220 TSecr=2141685

奇怪的是从第2662行开始,当没有明显的原因,我的设备发送RST数据包到服务器?为什么它会这样做呢?您可以看到2802~20s之后发生的连接终止(这是我的超时值)。问题是,当设备发送RST数据包HttpClient.execute没有返回时,它就在那里!

在配置我的客户端时,我可能错过了什么?

private static DefaultHttpClient newClient()
{
    HttpParams params = new BasicHttpParams();

    ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(30));
    ConnManagerParams.setMaxTotalConnections(params, 100);

    HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
    HttpProtocolParams.setUseExpectContinue(params, false);
    HttpProtocolParams.setUserAgent(params, "XXXXX XXXXXXXXXX/1.0");
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

    HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT);
    HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT);
    HttpConnectionParams.setSocketBufferSize(params, 8192);
    HttpConnectionParams.setStaleCheckingEnabled(params, true);

    SchemeRegistry reg = new SchemeRegistry();
    reg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    reg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
    ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(params, reg);

    DefaultHttpClient client = new DefaultHttpClient(mgr, params);

    return client;
}

或许它与我发出请求的方式有关?

private JSONObject performRequest(String url, JSONObject values) 
        throws ClientProtocolException, IOException, JSONException {
    HttpPost httpPost = new HttpPost(url);
    httpPost.setHeader("content-type", "application/json");
    httpPost.setHeader(HTTP.CONN_DIRECTIVE,HTTP.CONN_CLOSE);

    StringEntity requestEntity;
    requestEntity = new StringEntity(values.toString(), HTTP.UTF_8);
    httpPost.setEntity(requestEntity);

    HttpResponse response;
    HttpEntity responseEntity = null;
    String responseString;
    try {
        //this is the line that never returns
        response = _httpClient.execute(httpPost);
        responseEntity = response.getEntity();          
        responseString = EntityUtils.toString(responseEntity);
    } finally {
        if (responseEntity != null)
            responseEntity.consumeContent();
    }
    String d = new JSONObject(responseString).getString("d");
    if (d.length() > 0)
        return new JSONObject(d);
    else
        return new JSONObject();
}

我的应用程序中的所有Web服务调用都使用相同的HttpClient,多个线程可以访问此客户端。我假设使用ThreadSafeClientConnManager将提供我需要的线程安全性,但我想可能还有其他我错过的东西。

非常感谢任何帮助,我整天都在试着解决这个问题,一直在敲击键盘。

修改的 我想我应该提到这只发生在我使用机器名作为网址时,而不是我使用特定的IP地址。

2 个答案:

答案 0 :(得分:0)

我以前遇到过类似的问题。事实证明,我的POST主体中有一些服务器不喜欢的数据。在请求通过之前,我使用了反复试验来消除我扔进HttpPost对象的内容。

对我而言,我投入了一个糟糕的键值对。

换句话说,我相信你的问题在你的“价值”对象的某个地方。我的问题是我的POST请求中有JSON键“_b”。尝试删除JSON值,直到服务器停止超时。

还有一个提示:为了测试这个,我创建了一个应用程序,它只是重复发出一个网络请求,一个我知道很容易超时的应用程序,直到我得到超时。通常我会在前100个请求中超时。如果你这样做可能会有所帮助。

答案 1 :(得分:0)

想出来!在我的设备上运行configuration scripts dhcpcd之一并不同意我使用的硬件/驱动程序。我修改了脚本,它解决了错误的TCP / IP连接。

相关问题