Comment définir le délai d'expiration HttpResponse pour Android en Java

333

J'ai créé la fonction suivante pour vérifier l'état de la connexion:

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

Quand j'arrête le serveur pour tester l'exécution attend longtemps sur la ligne

HttpResponse response = httpClient.execute(method);

Est-ce que quelqu'un sait comment régler le délai afin d'éviter d'attendre trop longtemps?

Merci!

Niko Gamulin
la source

Réponses:

625

Dans mon exemple, deux délais d'attente sont définis. Le délai d'expiration de la connexion est lancé java.net.SocketTimeoutException: Socket is not connectedet le délai d'expiration du 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 vous souhaitez définir les paramètres d'un HTTPClient existant (par exemple DefaultHttpClient ou AndroidHttpClient), vous pouvez utiliser la fonction setParams () .

httpClient.setParams(httpParameters);
kuester2000
la source
1
@Thomas: J'ai édité ma réponse avec une solution pour votre cas d'utilisation
kuester2000
3
Que retournera HttpResponse si la connexion expire? Au moment où ma demande HTTP est faite, je vérifie ensuite le code d'état lors du retour de l'appel, mais j'obtiens une exception NullPointerException lors de la vérification de ce code si l'appel a expiré ... en gros, comment gérer la situation lorsque l'appel fait le timeout? (J'utilise un code très similaire à votre réponse donnée)
Tim
10
@jellyfish - Malgré la documentation, AndroidHttpClient n'étend pas DefaultHttpClient; il implémente plutôt HttpClient. Vous devrez utiliser DefaultHttpClient pour disposer de la méthode setParams (HttpParams).
Ted Hopp
3
Hé les gars, merci pour l'excellente réponse. Mais, je voudrais montrer un toast aux utilisateurs sur le délai de connexion ... de quelle manière je peux détecter quand la connexion arrive à expiration?
Arnab Chakraborty
2
Ça ne marche pas. J'ai testé sur mon Sony et ma moto, ils sont tous cachés.
thecr0w du
13

Pour définir des paramètres sur le client:

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

J'ai utilisé cela avec succès sur JellyBean, mais devrait également fonctionner pour les anciennes plates-formes ....

HTH


la source
quelle est la relation avec HttpClient?
Sazzad Hissain Khan
8

Si vous utilisez la bibliothèque client http de Jakarta, vous pouvez faire quelque chose comme:

        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
la source
5
HttpClientParams.CONNECTION_MANAGER_TIMEOUT est inconnu
Tawani
Vous devez utiliser client.getParams (). SetIntParameter (..) pour les paramètres * _TIMEOUT
loafoe
Comment trouver? L'appareil est connecté au wifi mais les données ne sont pas réellement actives via le wifi.
Ganesh Katikar
7

Si vous utilisez le client http par défaut, voici comment le faire en utilisant les paramètres http par défaut:

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

Le crédit d'origine va à http://www.jayway.com/2009/03/17/configuring-timeout-with-apache-httpclient-40/

Apprenez OpenGL ES
la source
5

Pour ceux qui disent que la réponse de @ kuester2000 ne fonctionne pas, sachez que les demandes HTTP, essayez d'abord de trouver l'IP hôte avec une demande DNS, puis faites la demande HTTP réelle au serveur, vous devrez donc peut-être également définir un délai d'expiration de la demande DNS.

Si votre code a fonctionné sans le délai d'expiration de la demande DNS, c'est parce que vous êtes en mesure d'atteindre un serveur DNS ou que vous atteignez le cache DNS Android. À propos, vous pouvez vider ce cache en redémarrant l'appareil.

Ce code étend la réponse d'origine pour inclure une recherche DNS manuelle avec un délai d'expiration personnalisé:

//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éthode utilisée:

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

Cette classe provient de ce billet de blog . Allez vérifier les remarques si vous allez l'utiliser.

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
la source
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
la source
Incomplet. Quelle est la relation avec HttpClient?
Sazzad Hissain Khan
1

vous pouvez créer une instance HttpClient en passant avec Httpclient-android-4.3.5, cela peut bien fonctionner.

 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
la source
1

Une option consiste à utiliser le client OkHttp , de Square.

Ajouter la dépendance de bibliothèque

Dans le build.gradle, incluez cette ligne:

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

Où se x.x.xtrouve la version de bibliothèque souhaitée.

Définissez le client

Par exemple, si vous souhaitez définir un délai d'expiration de 60 secondes, procédez comme suit:

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

ps: Si votre version minSdk est supérieure à 8, vous pouvez utiliser TimeUnit.MINUTES. Ainsi, vous pouvez simplement utiliser:

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

Pour plus de détails sur les unités, voir TimeUnit .

androidevil
la source
Dans la version actuelle d'OkHttp, les délais d'expiration doivent être définis différemment: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/ConfigureTimeouts.java
thijsonline
1

Si vous utilisez le HttpURLConnection, appelez setConnectTimeout()comme décrit ici :

URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);
Bruno Peres
la source
La description ressemble plus à la temporisation pour établir la connexion, au lieu de la requête 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
la source
Quel serveur représente-t-il? "8.8.8.8", 53
Junaed