Come impostare il timeout di HttpResponse per Android in Java


333

Ho creato la seguente funzione per controllare lo stato della connessione:

private void checkConnectionStatus() {
    HttpClient httpClient = new DefaultHttpClient();

    try {
      String url = "http://xxx.xxx.xxx.xxx:8000/GaitLink/"
                   + strSessionString + "/ConnectionStatus";
      Log.d("phobos", "performing get " + url);
      HttpGet method = new HttpGet(new URI(url));
      HttpResponse response = httpClient.execute(method);

      if (response != null) {
        String result = getResponse(response.getEntity());
        ...

Quando spengo il server per il test, l'esecuzione attende a lungo in linea

HttpResponse response = httpClient.execute(method);

Qualcuno sa come impostare il timeout per evitare di aspettare troppo a lungo?

Grazie!

Risposte:


625

Nel mio esempio, sono impostati due timeout. Viene generato il timeout della connessione java.net.SocketTimeoutException: Socket is not connectede il timeout del socket java.net.SocketTimeoutException: The operation timed out.

HttpGet httpGet = new HttpGet(url);
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used. 
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT) 
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpResponse response = httpClient.execute(httpGet);

Se si desidera impostare i parametri di qualsiasi HTTPClient esistente (ad esempio DefaultHttpClient o AndroidHttpClient) è possibile utilizzare la funzione setParams () .

httpClient.setParams(httpParameters);

1
Thomas: ho modificato la mia risposta con una soluzione per il tuo caso d'uso
kuester2000

3
Cosa restituirà HttpResponse in caso di timeout della connessione? Al momento, una volta effettuata la mia richiesta HTTP, controllo il codice di stato al ritorno della chiamata, tuttavia ricevo una NullPointerException quando controllo questo codice se la chiamata è scaduta ... in sostanza, come gestisco la situazione quando la chiamata fa il timeout? (Sto usando un codice molto simile alla tua risposta data)
Tim

10
@jellyfish - Nonostante la documentazione, AndroidHttpClient non estende DefaultHttpClient; piuttosto, implementa HttpClient. Dovrai usare DefaultHttpClient per avere a disposizione il metodo setParams (HttpParams).
Ted Hopp,

3
Ehi ragazzi, ho una risposta eccellente. Ma vorrei mostrare un brindisi agli utenti in caso di timeout della connessione ... in che modo posso rilevare il timeout della connessione?
Arnab Chakraborty,

2
Non funziona Ho provato su Sony e Moto, sono tutti nascosti.
giovedì

13

Per configurare le impostazioni sul client:

AndroidHttpClient client = AndroidHttpClient.newInstance("Awesome User Agent V/1.0");
HttpConnectionParams.setConnectionTimeout(client.getParams(), 3000);
HttpConnectionParams.setSoTimeout(client.getParams(), 5000);

L'ho usato con successo su JellyBean, ma dovrebbe funzionare anche per piattaforme meno recenti ...

HTH


qual è la relazione con HttpClient?
Sazzad Hissain Khan,

8

Se stai usando Jakarta libreria client http puoi fare qualcosa del tipo:

        HttpClient client = new HttpClient();
        client.getParams().setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, new Long(5000));
        client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, new Integer(5000));
        GetMethod method = new GetMethod("http://www.yoururl.com");
        method.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, new Integer(5000));
        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
        int statuscode = client.executeMethod(method);

5
HttpClientParams.CONNECTION_MANAGER_TIMEOUT è sconosciuto
Tawani,

Dovresti usare client.getParams (). SetIntParameter (..) per i parametri * _TIMEOUT
loafoe

Come trovare? Il dispositivo è connesso al Wi-Fi ma i dati non sono effettivamente attivi attraverso il Wi-Fi.
Ganesh Katikar,


5

Per coloro che affermano che la risposta di @ kuester2000 non funziona, tenere presente che le richieste HTTP, prima provare a trovare l'IP host con una richiesta DNS e quindi effettuare l'effettiva richiesta HTTP al server, quindi potrebbe essere necessario impostare un timeout per la richiesta DNS.

Se il tuo codice ha funzionato senza il timeout per la richiesta DNS è perché sei in grado di raggiungere un server DNS o stai colpendo la cache DNS Android. A proposito, puoi cancellare questa cache riavviando il dispositivo.

Questo codice estende la risposta originale per includere una ricerca DNS manuale con un timeout personalizzato:

//Our objective
String sURL = "http://www.google.com/";
int DNSTimeout = 1000;
int HTTPTimeout = 2000;

//Get the IP of the Host
URL url= null;
try {
     url = ResolveHostIP(sURL,DNSTimeout);
} catch (MalformedURLException e) {
    Log.d("INFO",e.getMessage());
}

if(url==null){
    //the DNS lookup timed out or failed.
}

//Build the request parameters
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, HTTPTimeout);
HttpConnectionParams.setSoTimeout(params, HTTPTimeout);

DefaultHttpClient client = new DefaultHttpClient(params);

HttpResponse httpResponse;
String text;
try {
    //Execute the request (here it blocks the execution until finished or a timeout)
    httpResponse = client.execute(new HttpGet(url.toString()));
} catch (IOException e) {
    //If you hit this probably the connection timed out
    Log.d("INFO",e.getMessage());
}

//If you get here everything went OK so check response code, body or whatever

Metodo usato:

//Run the DNS lookup manually to be able to time it out.
public static URL ResolveHostIP (String sURL, int timeout) throws MalformedURLException {
    URL url= new URL(sURL);
    //Resolve the host IP on a new thread
    DNSResolver dnsRes = new DNSResolver(url.getHost());
    Thread t = new Thread(dnsRes);
    t.start();
    //Join the thread for some time
    try {
        t.join(timeout);
    } catch (InterruptedException e) {
        Log.d("DEBUG", "DNS lookup interrupted");
        return null;
    }

    //get the IP of the host
    InetAddress inetAddr = dnsRes.get();
    if(inetAddr==null) {
        Log.d("DEBUG", "DNS timed out.");
        return null;
    }

    //rebuild the URL with the IP and return it
    Log.d("DEBUG", "DNS solved.");
    return new URL(url.getProtocol(),inetAddr.getHostAddress(),url.getPort(),url.getFile());
}   

Questa lezione proviene da questo post sul blog . Vai e controlla i commenti se lo userai.

public static class DNSResolver implements Runnable {
    private String domain;
    private InetAddress inetAddr;

    public DNSResolver(String domain) {
        this.domain = domain;
    }

    public void run() {
        try {
            InetAddress addr = InetAddress.getByName(domain);
            set(addr);
        } catch (UnknownHostException e) {
        }
    }

    public synchronized void set(InetAddress inetAddr) {
        this.inetAddr = inetAddr;
    }
    public synchronized InetAddress get() {
        return inetAddr;
    }
}

1
HttpParams httpParameters = new BasicHttpParams();
            HttpProtocolParams.setVersion(httpParameters, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(httpParameters,
                    HTTP.DEFAULT_CONTENT_CHARSET);
            HttpProtocolParams.setUseExpectContinue(httpParameters, true);

            // Set the timeout in milliseconds until a connection is
            // established.
            // The default value is zero, that means the timeout is not used.
            int timeoutConnection = 35 * 1000;
            HttpConnectionParams.setConnectionTimeout(httpParameters,
                    timeoutConnection);
            // Set the default socket timeout (SO_TIMEOUT)
            // in milliseconds which is the timeout for waiting for data.
            int timeoutSocket = 30 * 1000;
            HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

Non completo. Qual è la relazione con HttpClient?
Sazzad Hissain Khan,

1

puoi creare l'istanza di HttpClient a proposito con Httpclient-android-4.3.5, può funzionare bene.

 SSLContext sslContext = SSLContexts.createSystemDefault();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslContext,
                SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
                RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setCircularRedirectsAllowed(false).setConnectionRequestTimeout(30*1000).setConnectTimeout(30 * 1000).setMaxRedirects(10).setSocketTimeout(60 * 1000);
        CloseableHttpClient hc = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(requestConfigBuilder.build()).build();

1

Un'opzione è utilizzare il client OkHttp , da Square.

Aggiungi la dipendenza dalla libreria

In build.gradle, includere questa riga:

compile 'com.squareup.okhttp:okhttp:x.x.x'

Dov'è x.x.xla versione della libreria desiderata.

Imposta il client

Ad esempio, se si desidera impostare un timeout di 60 secondi, procedere come segue:

final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);

ps: se minSdkVersion è maggiore di 8, è possibile utilizzare TimeUnit.MINUTES. Quindi, puoi semplicemente usare:

okHttpClient.setReadTimeout(1, TimeUnit.MINUTES);
okHttpClient.setConnectTimeout(1, TimeUnit.MINUTES);

Per maggiori dettagli sulle unità, vedere TimeUnit .


Nella versione corrente di OkHttp, i timeout devono essere impostati in modo diverso: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/ConfigureTimeouts.java
thijsonline

1

Se si utilizza il HttpURLConnection, chiamare setConnectTimeout()come descritto qui :

URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);

La descrizione è più simile al timeout per stabilire la connessione, anziché alla richiesta http?
user2499800,

0
public boolean isInternetWorking(){
    try {
        int timeOut = 5000;
        Socket socket = new Socket();
        SocketAddress socketAddress = new InetSocketAddress("8.8.8.8",53);
        socket.connect(socketAddress,timeOut);
        socket.close();
        return true;
    } catch (IOException e) {
        //silent
    }
    return false;
}

Quale server rappresenta? "8.8.8.8", 53
Junaed
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.