2012-03-29 29 views
20

Sto sviluppando un'applicazione a lunga esecuzione che utilizza pesantemente HttpClient da apache.HttpClient bloccato senza eccezioni

Durante la mia prima esecuzione di test, l'applicazione ha funzionato perfettamente finché non si è bloccata. Non è stato fermato, non ha fatto eccezione, si limita a stare lì senza far nulla.

Ho fatto una seconda corsa proprio ora e ho fermato il tempo e si è fermato dopo ca. 24 ore di gara in corso. Inoltre ho notato che la connessione Internet del mio portatile su cui l'ho installato era terminata nel momento esatto in cui l'applicazione si bloccava. Ho dovuto riavviare il mio adattatore WLAN per riavviare la rete.

L'applicazione, tuttavia, non è tornata a funzionare dopo che la connessione era di nuovo attiva. E ora, è bloccato di nuovo.

C'è qualche controller di timeout di cui non sono a conoscenza in HttpClient? Perché la mia applicazione non lancia un'eccezione quando la connessione non funziona?

La parte che utilizza il client si presenta come segue;

public HttpUtil(ConfigUtil config) { 
    this.config = config; 

    client = new DefaultHttpClient(); 
    client.getParams().setParameter(HttpProtocolParams.USER_AGENT, this.config.getProperty("httputil.userAgent")); 
} 

public String getContentAsString(String url) throws ParseException, ClientProtocolException, IOException { 
    return EntityUtils.toString(
      client.execute(
        new HttpGet(url)).getEntity()); 
} 

L'applicazione chiama ripetutamente lo httputil.getContentAsString() sugli URL necessari.

+0

Forse la tua entità è una stringa vuota. – kasavbere

+0

Quindi il mio metodo restituirebbe ancora quella stringa vuota, non è vero? O lanciare un'eccezione almeno? –

+1

Ho lo stesso problema. httpEntity.consumeContent() salvami. http://stackoverflow.com/questions/9505358/android-httpclient-hangs-on-second-request-to-the-server-connection-timed-out – JamesC

risposta

8

Questo codice è ora deprecato (ottenere HttpParams, ecc.).Un modo migliore è:

RequestConfig defaultRequestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.BEST_MATCH).setExpectContinueEnabled(true).setStaleConnectionCheckEnabled(true).setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)).setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build(); 

HttpGet httpGet = new HttpGet(url);  
RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig).setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000).build(); 
httpGet.setConfig(requestConfig); 
6

Non hai detto quale versione di HttpClient stai usando, ma supponendo che sia la versione 4, this blog article spiega cosa fare.

DefaultHttpClient httpClient = new DefaultHttpClient(); 
HttpParams params = httpClient.getParams(); 
HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeoutMillis); 
HttpConnectionParams.setSoTimeout(httpParams, socketTimeoutMillis); 
+2

Credo che ora sia deprecato –

3

Per impostazione predefinita, HttpClient non esegue il timeout (che causa più problemi di quanto non aiuti). Quello che stai descrivendo potrebbe essere un problema hardware, se il tuo adattatore di rete è morto, HttpClient si bloccherà.

Ecco il parameters set di HttpParams come parte del costruttore per DefaultHttpClient compreso

http.socket.timeout: definisce il timeout presa (SO_TIMEOUT) in millisecondi, che è il timeout per l'attesa per dati o, mettere in modo diverso, un periodo massimo di inattività tra due pacchetti dati consecutivi). Un valore di timeout pari a zero viene interpretato come un timeout infinito . Questo parametro si aspetta un valore di tipo java.lang.Integer. Se questo parametro non è impostato, le operazioni di lettura non scadono (timeout infinito ).

Questo imposterà un timeout sulla connessione, quindi dopo il timeout impostato verrà generata un'eccezione.

3

Ho impostato tutti i timeout in modo corretto ma ho scoperto che l'URL contiene http chunking ma non invia risultati (funziona bene in chrome, ma nel client http si blocca per sempre anche con il timeout impostato). Fortunatamente possiedo il server e restituisco alcuni rifiuti e non si blocca più. Questo sembra un bug molto particolare in quel client http che non gestisce bene una specie di chunking vuoto (anche se potrei essere lontano) .... So solo che si blocca ogni volta su quello stesso url con dati vuoti e quell'URL è http chunking csv scaricare di nuovo al nostro client http.

6

A partire dalla versione 4.4, entrambe le risposte da parte degli utenti user2393012 e Stephen C sono stati deprecati. Non sono sicuro che ci sia un altro modo per farlo, ma il modo in cui lo faccio è utilizzando un paradigma di builder, HTTPClientBuilder.

Es.

HttpClients.custom().setConnectionTimeToLive(1, TimeUnit.MINUTES).build() 

A molto simile (in realtà sarebbe stato un problema PO) problema di quanto OP menzionato anche accade, ma è dovuto Apache modificando le connessioni simultanee predefinite per solo due connessioni per cliente. La soluzione a questo sarebbe aumentare le connessioni massime o chiuderle se possibile.

Per aumentare le connessioni max:

HttpClients.custom().setMaxConnPerRoute(100000).build() 

per chiudere le connessioni, è possibile utilizzare un BasicHttpClientConnectionManager e chiamare il metodo close per

3

ho avuto lo stesso problema, si è bloccato perché non l'ho fatto chiudi DefaultHttpClient.
Quindi questo è sbagliato:

try{ 
    DefaultHttpClient httpclient = new DefaultHttpClient(); 
    ... 
} catch (Exception e){ 
    e.PrintStackTrace(); 
} 

E questo è giusto:

try (DefaultHttpClient httpclient = new DefaultHttpClient()){ 
    ... 
} catch (Exception e){ 
    e.PrintStackTrace(); 
} 

Speranza che aiuta qualcuno.

4

ho dato una risposta simile in un altro thread (HttpClient hangs on socketRead0 with successfully executed method)

Nel mio caso, mi è stato l'impostazione del connectionTimeout e socketTimeout in merito alla richiesta, ma non sulla presa di connessione utilizzato durante la creazione della connessione SSL. Di conseguenza, a volte mi impiccherei durante l'handshake SSL. Di seguito è riportato un codice che imposta tutti i 3 timeout utilizzando la v4.4 (testata anche nella v4.5)

// Configure the socket timeout for the connection, incl. ssl tunneling 
connManager = new PoolingHttpClientConnectionManager(); 
connManager.setMaxTotal(200); 
connManager.setDefaultMaxPerRoute(100); 

SocketConfig sc = SocketConfig.custom() 
    .setSoTimeout(soTimeoutMs) 
    .build(); 

connManager.setDefaultSocketConfig(sc); 

HttpClient client = HttpClients.custom() 
      .setConnectionManager(connManager) 
      .setConnectionManagerShared(true) 
      .build(); 

// configure the timeouts (socket and connection) for the request 
RequestConfig.Builder config = = RequestConfig.copy(RequestConfig.DEFAULT); 
config.setConnectionRequestTimeout(connectionTimeoutMs); 
config.setSocketTimeout(socketTimeoutMs); 

HttpRequestBase req = new HttpGet(uri); 
req.setConfig(config.build()); 

client.execute(req);