So legen Sie das HttpResponse-Zeitlimit für Android in Java fest

333

Ich habe die folgende Funktion zum Überprüfen des Verbindungsstatus erstellt:

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

Wenn ich den Server zum Testen herunterfahre, wartet die Ausführung lange in der Leitung

HttpResponse response = httpClient.execute(method);

Weiß jemand, wie man das Timeout einstellt, um nicht zu lange zu warten?

Vielen Dank!

Niko Gamulin
quelle

Antworten:

625

In meinem Beispiel sind zwei Zeitüberschreitungen festgelegt. Das Verbindungs-Timeout wird ausgelöst java.net.SocketTimeoutException: Socket is not connectedund das Socket-Timeout 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);

Wenn Sie die Parameter eines vorhandenen HTTPClient (z. B. DefaultHttpClient oder AndroidHttpClient) festlegen möchten, können Sie die Funktion setParams () verwenden .

httpClient.setParams(httpParameters);
kuester2000
quelle
1
@ Thomas: Ich habe meine Antwort mit einer Lösung für Ihren Anwendungsfall bearbeitet
kuester2000
3
Was gibt die HttpResponse zurück, wenn die Verbindung abläuft? In dem Moment, in dem meine HTTP-Anfrage gestellt wurde, überprüfe ich den Statuscode bei der Rückgabe des Anrufs. Ich erhalte jedoch eine NullPointerException, wenn ich diesen Code überprüfe, wenn der Anruf abgelaufen ist. Wie gehe ich im Grunde mit der Situation um, wenn der Anruf erfolgt? macht Timeout? (Ich verwende einen sehr ähnlichen Code wie Ihre Antwort)
Tim
10
@jellyfish - Trotz der Dokumentation erweitert AndroidHttpClient DefaultHttpClient nicht . Vielmehr wird HttpClient implementiert. Sie müssen DefaultHttpClient verwenden, um die Methode setParams (HttpParams) verfügbar zu haben.
Ted Hopp
3
Hey Leute, ich danke Ihnen für die hervorragende Antwort. Aber ich möchte den Benutzern beim Verbindungs-Timeout einen Toast zeigen ... Wie kann ich feststellen, wann die Verbindung abläuft?
Arnab Chakraborty
2
Funktioniert nicht Ich habe auf meinem Sony und Moto getestet, sie werden alle versteckt.
thecr0w
13

So legen Sie Einstellungen auf dem Client fest:

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

Ich habe dies erfolgreich auf JellyBean verwendet, sollte aber auch für ältere Plattformen funktionieren ....

HTH


quelle
Wie ist die Beziehung zu HttpClient?
Sazzad Hissain Khan
8

Wenn Sie die http-Client-Bibliothek von Jakarta verwenden, können Sie Folgendes tun:

        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
quelle
5
HttpClientParams.CONNECTION_MANAGER_TIMEOUT ist unbekannt
Tawani
Sie sollten client.getParams (). SetIntParameter (..) für die * _TIMEOUT-Parameter verwenden
loafoe
Wie findet man? Das Gerät ist mit WLAN verbunden, aber es werden keine aktiven Daten über WLAN übertragen.
Ganesh Katikar
7

Wenn Sie den Standard-http-Client verwenden, gehen Sie wie folgt vor, indem Sie die Standard-http-Parameter verwenden:

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

Das ursprüngliche Guthaben geht an http://www.jayway.com/2009/03/17/configuring-timeout-with-apache-httpclient-40/

Lernen Sie OpenGL ES
quelle
5

Wenn Sie sagen, dass die Antwort von @ kuester2000 nicht funktioniert, beachten Sie bitte, dass HTTP-Anforderungen zuerst versuchen, die Host-IP mit einer DNS-Anforderung zu finden, und dann die eigentliche HTTP-Anforderung an den Server senden, sodass Sie möglicherweise auch eine festlegen müssen Zeitüberschreitung für die DNS-Anforderung.

Wenn Ihr Code ohne das Zeitlimit für die DNS-Anforderung funktioniert hat, liegt dies daran, dass Sie einen DNS-Server erreichen können oder den Android-DNS-Cache erreichen. Übrigens können Sie diesen Cache löschen, indem Sie das Gerät neu starten.

Dieser Code erweitert die ursprüngliche Antwort um eine manuelle DNS-Suche mit einem benutzerdefinierten Zeitlimit:

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

Verwendete Methode:

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

Diese Klasse stammt aus diesem Blogbeitrag . Überprüfen Sie die Anmerkungen, ob Sie sie verwenden werden.

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
quelle
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
quelle
Unvollständig. Wie ist die Beziehung zu HttpClient?
Sazzad Hissain Khan
1

Sie können HttpClient-Instanz übrigens mit Httpclient-android-4.3.5 erstellen, es kann gut funktionieren.

 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
quelle
1

Eine Option ist die Verwendung des OkHttp- Clients von Square.

Fügen Sie die Bibliotheksabhängigkeit hinzu

Fügen Sie im build.gradle die folgende Zeile ein:

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

Wo x.x.xist die gewünschte Bibliotheksversion?

Stellen Sie den Client ein

Wenn Sie beispielsweise eine Zeitüberschreitung von 60 Sekunden festlegen möchten, gehen Sie folgendermaßen vor:

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

ps: Wenn Ihre minSdkVersion größer als 8 ist, können Sie verwenden TimeUnit.MINUTES. Sie können also einfach Folgendes verwenden:

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

Weitere Informationen zu den Einheiten finden Sie unter TimeUnit .

Androidevil
quelle
In der aktuellen Version von OkHttp müssen Zeitüberschreitungen anders festgelegt werden: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/ConfigureTimeouts.java
thijsonline
1

Wenn Sie das verwenden HttpURLConnection, rufen Sie setConnectTimeout()wie hier beschrieben an :

URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);
Bruno Peres
quelle
Die Beschreibung ähnelt eher dem Zeitlimit zum Herstellen der Verbindung anstelle der http-Anforderung.
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
quelle
Welchen Server repräsentiert es? 8.8.8.8, 53
Junaed