2013-02-06 59 views
0

在我的應用程序中嘗試使用HttpClient時,我遇到了一個相當迷惑的難題。看似隨意,HttpClient.execute(HttpRequest)永遠不會回來!那麼......如果我使用HttpConnectionParams.setConnectionTimeout(HttpParams, int)來設置超時,它會引發超時異常。否則我的後臺線程將永遠掛起。Android HttpClient在執行期間發送第一個數據包

我試着在陽光下的一切來彌補問題,但無濟於事。留下沒有其他選擇我採取了一個問題的數據包捕獲,並發現令人驚訝的事情! (也許並不奇怪,我不是一個真正的網絡傢伙)

成功的呼叫:

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

同樣HttpClient用於在我的應用程序的所有Web服務調用和多線程可以訪問此客戶端。我假定使用ThreadSafeClientConnManager將提供我需要的線程安全性,但我猜可能還有其他東西我錯過了。

任何幫助非常感謝,我一直在努力解決這個問題,一直在敲着我的頭對着鍵盤。

編輯 我想我應該提到這一點,只有當我使用機器名作爲URL時,沒有如果我使用特定的IP地址。

回答

0

我以前有過類似的問題。事實證明,我在POST機構中有一些服務器不喜歡的數據。我使用了試驗和錯誤來消除我在投入HttpPost對象之前拋出的內容,直到請求完成。

對我來說,我扔了一個糟糕的鍵值對。

換句話說,我相信你的問題是在你的「價值」對象的某個地方。我的問題是我的POST請求中有JSON密鑰「_b」。嘗試刪除JSON值直到服務器停止超時。

一個提示:爲了測試這一點,我創建了一個應用程序,只是反覆地做一個網絡請求,一個我所知道的是容易出現超時,在一個循環,直到我得到超時。通常我會在前100個請求中超時。如果你這樣做可能會有所幫助。

+0

我無法想象這是問題,因爲我看到兩個相同請求之間的不同行爲。 – FlyingStreudel

+0

如果您看到不同的行爲,那麼根據定義,請求之間必定有差異。你能提供你正在提出的請求的例子嗎? – WindyB

+0

該問題不在Web服務上,問題是設備終止連接請求。這從呼叫呼叫中發生不一致。 – FlyingStreudel

相關問題