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!

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

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


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

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


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

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

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

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 .



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

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

Server mana yang diwakilinya? "8.8.8.8", 53
Junaed
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.