Cómo configurar el tiempo de espera de HttpResponse para Android en Java

333

He creado la siguiente función para verificar el estado de la conexión:

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

Cuando apago el servidor para probar, la ejecución espera mucho tiempo en la línea

HttpResponse response = httpClient.execute(method);

¿Alguien sabe cómo configurar el tiempo de espera para evitar esperar demasiado?

¡Gracias!

Niko Gamulin
fuente

Respuestas:

625

En mi ejemplo, se establecen dos tiempos de espera. El tiempo de espera de conexión de lanza java.net.SocketTimeoutException: Socket is not connectedy el tiempo de espera de 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);

Si desea establecer los parámetros de cualquier HTTPClient existente (por ejemplo, DefaultHttpClient o AndroidHttpClient) puede usar la función setParams () .

httpClient.setParams(httpParameters);
kuester2000
fuente
1
@Thomas: he editado mi respuesta con una solución para su caso de uso
kuester2000
3
¿Qué devolverá el HttpResponse si se agota el tiempo de espera de la conexión? En el momento en que se realiza mi solicitud HTTP, luego verifico el código de estado al regresar la llamada, sin embargo, recibo una NullPointerException cuando verifico este código si la llamada ha expirado ... básicamente, ¿cómo manejo la situación cuando la llamada hace tiempo de espera? (Estoy usando un código muy similar a la respuesta dada)
Tim
10
@jellyfish: a pesar de la documentación, AndroidHttpClient no extiende DefaultHttpClient; más bien, implementa HttpClient. Deberá usar DefaultHttpClient para tener disponible el método setParams (HttpParams).
Ted Hopp
3
Hola chicos, gracias por la excelente respuesta. Pero, me gustaría mostrar un brindis por los usuarios en el tiempo de espera de la conexión ... ¿alguna forma de detectar cuándo se agota el tiempo de conexión?
Arnab Chakraborty
2
No funciona Probé en mi Sony y Moto, todos se acomodan.
thecr0w
13

Para establecer la configuración en el cliente:

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

Lo he usado con éxito en JellyBean, pero también debería funcionar para plataformas más antiguas ...

HTH


fuente
¿Cuál es la relación con HttpClient?
Sazzad Hissain Khan
8

Si está utilizando la biblioteca de cliente http de Yakarta, puede hacer algo como:

        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);
Pablo Santa Cruz
fuente
55
HttpClientParams.CONNECTION_MANAGER_TIMEOUT es desconocido
Tawani
Debe usar client.getParams (). SetIntParameter (..) para los parámetros * _TIMEOUT
loafoe
¿Como encontrar? El dispositivo está conectado a wifi, pero en realidad no hay datos activos que lleguen a través de wifi.
Ganesh Katikar
7

Si está utilizando el cliente http predeterminado, a continuación se explica cómo hacerlo utilizando los parámetros http predeterminados:

HttpClient client = new DefaultHttpClient();
HttpParams params = client.getParams();
HttpConnectionParams.setConnectionTimeout(params, 3000);
HttpConnectionParams.setSoTimeout(params, 3000);

El crédito original va a http://www.jayway.com/2009/03/17/configuring-timeout-with-apache-httpclient-40/

Aprende OpenGL ES
fuente
5

Para aquellos que dicen que la respuesta de @ kuester2000 no funciona, tenga en cuenta que las solicitudes HTTP, primero intente encontrar la IP del host con una solicitud DNS y luego realice la solicitud HTTP real al servidor, por lo que también puede necesitar configurar un tiempo de espera para la solicitud de DNS.

Si su código funcionó sin el tiempo de espera para la solicitud DNS es porque puede acceder a un servidor DNS o está accediendo al caché DNS de Android. Por cierto, puede borrar este caché reiniciando el dispositivo.

Este código extiende la respuesta original para incluir una búsqueda DNS manual con un tiempo de espera personalizado:

//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

Método utilizado:

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

Esta clase es de esta publicación de blog . Ve y verifica los comentarios si lo vas a usar.

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;
    }
}
David Darias
fuente
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);
Sandeep
fuente
Sin completar. ¿Cuál es la relación con HttpClient?
Sazzad Hissain Khan
1

puede crear una instancia de HttpClient por cierto con Httpclient-android-4.3.5, puede funcionar bien.

 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();
Foxundermon
fuente
1

Una opción es usar el cliente OkHttp , de Square.

Agregar la dependencia de la biblioteca

En build.gradle, incluya esta línea:

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

¿Dónde x.x.xestá la versión de biblioteca deseada?

Establecer el cliente

Por ejemplo, si desea establecer un tiempo de espera de 60 segundos, haga lo siguiente:

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

ps: si tu minSdkVersion es mayor que 8, puedes usarlo TimeUnit.MINUTES. Entonces, simplemente puede usar:

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

Para más detalles sobre las unidades, vea TimeUnit .

androidevil
fuente
En la versión actual de OkHttp, los tiempos de espera deben configurarse de manera diferente: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/ConfigureTimeouts.java
thijsonline
1

Si está utilizando HttpURLConnection, llame setConnectTimeout()como se describe aquí :

URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);
Bruno Peres
fuente
La descripción es más como el tiempo de espera para establecer la conexión, en lugar de la solicitud 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;
}
Eco4ndly
fuente
¿Qué servidor representa? "8.8.8.8", 53
Junaed