Jak ustawić limit czasu HttpResponse dla Androida w Javie


333

Utworzyłem następującą funkcję do sprawdzania stanu połączenia:

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

Kiedy zamykam serwer do testowania wykonanie długo czeka w kolejce

HttpResponse response = httpClient.execute(method);

Czy ktoś wie, jak ustawić limit czasu, aby uniknąć zbyt długiego oczekiwania?

Dzięki!

Odpowiedzi:


625

W moim przykładzie ustawione są dwa limity czasu. Upłynął limit czasu połączenia java.net.SocketTimeoutException: Socket is not connectedi limit czasu gniazda 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);

Jeśli chcesz ustawić parametry dowolnego istniejącego HTTPClient (np. DefaultHttpClient lub AndroidHttpClient), możesz użyć funkcji setParams () .

httpClient.setParams(httpParameters);

1
@Thomas: Zredagowałem swoją odpowiedź z rozwiązaniem dla twojej
skrzynki użytkownika

3
Co zwróci HttpResponse, jeśli upłynie limit czasu połączenia? W chwili, gdy moje żądanie HTTP zostanie wykonane, sprawdzam kod statusu po powrocie połączenia, jednak otrzymuję NullPointerException podczas sprawdzania tego kodu, jeśli upłynął limit czasu połączenia ... w zasadzie, jak poradzić sobie z sytuacją, gdy połączenie czy upłynął limit czasu? (Używam bardzo podobnego kodu do podanej odpowiedzi)
Tim

10
@jellyfish - Pomimo dokumentacji AndroidHttpClient nie rozszerza DefaultHttpClient; raczej implementuje HttpClient. Musisz użyć DefaultHttpClient, aby mieć dostęp do metody setParams (HttpParams).
Ted Hopp,

3
Cześć wszystkim, dziękuję za doskonałą odpowiedź. Chciałbym jednak pokazać użytkownikom toast za przekroczenie limitu czasu połączenia ... w jaki sposób mogę wykryć przekroczenie limitu czasu połączenia?
Arnab Chakraborty

2
Nie działa Testowałem na moich Sony i Moto, wszystkie są schowane.
thecr0w

13

Aby ustawić ustawienia na kliencie:

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

Użyłem tego z powodzeniem na JellyBean, ale powinien również działać na starszych platformach ....

HTH


jaka jest relacja z HttpClient?
Sazzad Hissain Khan

8

Jeśli używasz biblioteki klienta http w Dżakarcie , możesz zrobić coś takiego:

        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 jest nieznany
Tawani

Powinieneś użyć client.getParams (). SetIntParameter (..) dla parametrów * _TIMEOUT
loafoe

Jak znaleźć? Urządzenie jest podłączone do Wi-Fi, ale dane faktycznie nie przechodzą przez Wi-Fi.
Ganesh Katikar


5

Dla tych, którzy twierdzą, że odpowiedź @ kuester2000 nie działa, należy pamiętać, że żądania HTTP, najpierw spróbuj znaleźć adres IP hosta za pomocą żądania DNS, a następnie wysyła rzeczywiste żądanie HTTP do serwera, więc może być konieczne ustawienie limit czasu dla żądania DNS.

Jeśli Twój kod działał bez limitu czasu dla żądania DNS, oznacza to, że możesz uzyskać dostęp do serwera DNS lub trafiasz do pamięci podręcznej DNS systemu Android. Nawiasem mówiąc, możesz wyczyścić pamięć podręczną, ponownie uruchamiając urządzenie.

Ten kod rozszerza oryginalną odpowiedź o ręczne wyszukiwanie DNS z niestandardowym limitem czasu:

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

Zastosowana metoda:

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

Ta klasa pochodzi z tego postu na blogu . Idź i sprawdź uwagi, jeśli będziesz ich używać.

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

Nie kompletny. Jaki jest stosunek do HttpClient?
Sazzad Hissain Khan

1

przy okazji z Httpclient-android-4.3.5 możesz utworzyć instancję HttpClient, może ona działać dobrze.

 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

Opcją jest użycie klienta OkHttp z Square.

Dodaj zależność od biblioteki

W build.gradle dołącz ten wiersz:

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

Gdzie x.x.xjest pożądana wersja biblioteki.

Ustaw klienta

Na przykład, jeśli chcesz ustawić limit czasu na 60 sekund, wykonaj następujące czynności:

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

ps: Jeśli twoja minSdkVersion jest większa niż 8, możesz użyć TimeUnit.MINUTES. Możesz więc po prostu użyć:

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

Aby uzyskać więcej informacji na temat jednostek, zobacz TimeUnit .



1

Jeśli używasz HttpURLConnection, zadzwoń setConnectTimeout()zgodnie z opisem tutaj :

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

Opis jest bardziej jak limit czasu na ustanowienie połączenia, zamiast żądania HTTP?
user2499800 24.0419

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;
}

Który serwer reprezentuje? „8.8.8.8”, 53
czerwca
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.