Cara mengatur batas waktu HttpResponse untuk Android di Java

333

Saya telah membuat fungsi berikut untuk memeriksa status koneksi:

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

Ketika saya menutup server untuk menguji eksekusi menunggu lama di baris

HttpResponse response = httpClient.execute(method);

Adakah yang tahu cara mengatur batas waktu agar tidak menunggu terlalu lama?

Terima kasih!

Niko Gamulin
sumber

Jawaban:

625

Dalam contoh saya, dua batas waktu ditetapkan. Waktu tunggu koneksi habis java.net.SocketTimeoutException: Socket is not connecteddan waktu habis soket 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);

Jika Anda ingin mengatur Parameter dari HTTPClient yang ada (misalnya DefaultHttpClient atau AndroidHttpClient) Anda dapat menggunakan fungsi setParams () .

httpClient.setParams(httpParameters);
kuester2000
sumber
1
@ Thomas: Saya telah mengedit jawaban saya dengan solusi untuk usecase Anda
kuester2000
3
Apa yang akan dikembalikan oleh HttpResponse jika koneksi terputus? Pada saat permintaan HTTP saya dibuat, saya kemudian memeriksa kode status pada panggilan kembali, namun saya mendapatkan NullPointerException ketika memeriksa kode ini jika panggilan telah kehabisan waktu ... pada dasarnya, bagaimana saya menangani situasi ketika panggilan apakah waktu habis? (Saya menggunakan kode yang sangat mirip dengan jawaban Anda yang diberikan)
Tim
10
@jellyfish - Meskipun dokumentasinya, AndroidHttpClient tidak memperpanjang DefaultHttpClient; melainkan menerapkan HttpClient. Anda harus menggunakan DefaultHttpClient untuk menyediakan metode setParams (HttpParams).
Ted Hopp
3
Hai teman-teman, terima kasih atas jawaban yang bagus Tapi, saya ingin bersulang kepada pengguna saat koneksi habis ... bagaimana saya bisa mendeteksi ketika koneksi terputus?
Arnab Chakraborty
2
Tidak bekerja Saya diuji pada Sony dan Moto saya, semuanya terselip.
thecr0w
13

Untuk mengatur pengaturan pada klien:

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

Saya telah menggunakan ini dengan sukses di JellyBean, tetapi seharusnya juga berfungsi untuk platform lama ....

HTH


sumber
apa hubungannya dengan HttpClient?
Sazzad Hissain Khan
8

Jika Anda menggunakan pustaka klien http Jakarta, maka Anda dapat melakukan sesuatu seperti:

        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
sumber
5
HttpClientParams.CONNECTION_MANAGER_TIMEOUT tidak diketahui
Tawani
Anda harus menggunakan client.getParams (). SetIntParameter (..) untuk params * _TIMEOUT
loafoe
Bagaimana menemukan? Perangkat terhubung ke wifi tetapi sebenarnya data tidak aktif melalui wifi.
Ganesh Katikar
7

Jika Anda menggunakan klien http default, berikut ini cara melakukannya menggunakan params http default:

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

Kredit asli diberikan ke http://www.jayway.com/2009/03/17/configuring-timeout-with-apache-httpclient-40/

Pelajari OpenGL ES
sumber
5

Bagi mereka yang mengatakan bahwa jawaban @ kuester2000 tidak berfungsi, harap perhatikan bahwa permintaan HTTP, pertama-tama coba temukan IP host dengan permintaan DNS dan kemudian buat permintaan HTTP aktual ke server, jadi Anda mungkin juga perlu mengatur batas waktu untuk permintaan DNS.

Jika kode Anda berfungsi tanpa batas waktu untuk permintaan DNS, itu karena Anda dapat mencapai server DNS atau Anda menekan cache Android DNS. Omong-omong, Anda dapat menghapus cache ini dengan memulai ulang perangkat.

Kode ini memperluas jawaban asli untuk menyertakan pencarian DNS manual dengan batas waktu khusus:

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

Metode yang digunakan:

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

Kelas ini dari posting blog ini . Pergi dan periksa pernyataan apakah Anda akan menggunakannya.

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
sumber
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
sumber
Tidak lengkap. Apa hubungannya dengan HttpClient?
Sazzad Hissain Khan
1

Anda dapat membuat contoh HttpClient dengan cara dengan Httpclient-android-4.3.5, ini dapat bekerja dengan baik.

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

Opsi adalah menggunakan klien OkHttp , dari Square.

Tambahkan ketergantungan perpustakaan

Di build.gradle, sertakan baris ini:

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

Di mana x.x.xversi perpustakaan yang diinginkan.

Atur klien

Misalnya, jika Anda ingin mengatur batas waktu 60 detik, lakukan cara ini:

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

ps: Jika minSdkVersion Anda lebih besar dari 8, Anda dapat menggunakan TimeUnit.MINUTES. Jadi, Anda cukup menggunakan:

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

Untuk detail lebih lanjut tentang unit, lihat TimeUnit .

androidevil
sumber
Dalam versi OkHttp saat ini, batas waktu perlu diatur secara berbeda: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/ConfigureTimeouts.java
thijsonline
1

Jika Anda menggunakan HttpURLConnection, panggil setConnectTimeout()seperti dijelaskan di sini :

URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);
Bruno Peres
sumber
Deskripsi lebih seperti batas waktu untuk membuat koneksi, bukan permintaan 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;
}
Ramah lingkungan
sumber
Server mana yang diwakilinya? "8.8.8.8", 53
Junaed