HttpURLConnection zaman aşımı ayarları


123

URL'nin bağlanması 5 saniyeden uzun sürerse yanlış döndürmek istiyorum - bu Java kullanılarak nasıl mümkün olabilir? İşte URL'nin geçerli olup olmadığını kontrol etmek için kullandığım kod

HttpURLConnection.setFollowRedirects(false);
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
con.setRequestMethod("HEAD");
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);

Yanıtlar:


201

HttpURLConnectionBir sahip setConnectTimeout yöntemi.

Zaman aşımını 5000 milisaniyeye ayarlayın ve ardından java.net.SocketTimeoutException

Kodunuz aşağıdaki gibi görünmelidir:


try {
   HttpURLConnection.setFollowRedirects(false);
   HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
   con.setRequestMethod("HEAD");

   con.setConnectTimeout(5000); //set timeout to 5 seconds

   return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
} catch (java.net.SocketTimeoutException e) {
   return false;
} catch (java.io.IOException e) {
   return false;
}



3
Değeri 10 dakikaya ayarlıyorum. Ancak java.net.ConnectException: Connection timed out: connect2 dakika dolmadan beni bir atıyor . Soruna neyin sebep olduğunu biliyor musunuz?
Pacerier

5
SocketTimeoutException, IOException'ın bir alt sınıfıdır. Her iki yakalama bloğu da aynı şeyi yaparsa, IOException'ı yakalayabilirsiniz.
spaaarky 21

2
@ spaaarky21 doğru. Ancak bir kullanıcı arabirimi oluşturuyorsanız ve kullanıcılarınıza bir zaman aşımı oluştuğunu bildirmek istiyorsanız, SocketTimeoutException'ı IOException'dan önce yakalamalısınız, yoksa erişilemez olacaktır.
Clocker

3
NB !!! setConnectTimeoutörtük olarak bağlanan yöntemlerden önce çağırmanız gerekir (temelde zaten bağlıysa IllegalStateException oluşturan tüm yöntemler). İdeal olarak setConnectTimeout (readTimeout) 'u.
Adam Gent

4
Benim için işe yaramadı. Ancak ekledikten sonra con.setReadTimeout()beklendiği gibi çalıştı.
Paulo

115

Zaman aşımını şu şekilde ayarlayabilirsiniz,

con.setConnectTimeout(connectTimeout);
con.setReadTimeout(socketTimeout);

2
Belirleyebileceğimiz maksimum zaman aşımı değeri nedir?
Pacerier

7
@Pacerier Dokümanlar bunu açıkça belirtmiyor. Değer negatifse bir IllegalArgumentException oluşturur (0 değeri süresiz olarak beklemek anlamına gelir). Zaman aşımı işaretsiz bir 32bit int olduğu için, maksimum zaman aşımının yaklaşık 49 gün olacağını tahmin ediyorum (bunun böyle bir değerin herhangi birine yardımcı olacağından ciddi olarak şüpheliyim).
Jay Sidri

1

HTTP Bağlantısı zaman aşımına uğramazsa, zaman aşımı denetleyicisini arka plan iş parçacığının kendisinde (AsyncTask, Service, vb.) Uygulayabilirsiniz, aşağıdaki sınıf, belirli bir süre sonra zaman aşımına uğrayan AsyncTask Özelleştirme için bir örnektir.

public abstract class AsyncTaskWithTimer<Params, Progress, Result> extends
    AsyncTask<Params, Progress, Result> {

private static final int HTTP_REQUEST_TIMEOUT = 30000;

@Override
protected Result doInBackground(Params... params) {
    createTimeoutListener();
    return doInBackgroundImpl(params);
}

private void createTimeoutListener() {
    Thread timeout = new Thread() {
        public void run() {
            Looper.prepare();

            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {

                    if (AsyncTaskWithTimer.this != null
                            && AsyncTaskWithTimer.this.getStatus() != Status.FINISHED)
                        AsyncTaskWithTimer.this.cancel(true);
                    handler.removeCallbacks(this);
                    Looper.myLooper().quit();
                }
            }, HTTP_REQUEST_TIMEOUT);

            Looper.loop();
        }
    };
    timeout.start();
}

abstract protected Result doInBackgroundImpl(Params... params);
}

Bunun için bir örnek

public class AsyncTaskWithTimerSample extends AsyncTaskWithTimer<Void, Void, Void> {

    @Override
    protected void onCancelled(Void void) {
        Log.d(TAG, "Async Task onCancelled With Result");
        super.onCancelled(result);
    }

    @Override
    protected void onCancelled() {
        Log.d(TAG, "Async Task onCancelled");
        super.onCancelled();
    }

    @Override
    protected Void doInBackgroundImpl(Void... params) {
        // Do background work
        return null;
    };
 }

Sadece cancel () için bir çağrı planlamak için yeni bir döngüleyici iş parçacığı oluşturmak kesinlikle gereksizdir. Bunu ana iş parçacığından yapabilirsiniz onPreExecute(). Ayrıca, görevi manuel olarak iptal ederseniz, sızıntıları önlemek için zamanlanmış aramayı da iptal etmelisiniz.
BladeCoder

Buradaki nokta, onPreExecute () 'de değil, yürütmede çok fazla zaman aldığında doInBackground ()' un ortasında AsyncTask'i iptal etmektir, ayrıca sadece çok fazla zaman alan ve diğerlerini tutan bu AsyncTask örneğini iptal etmek istiyorum, çok takdir ediyorum Görüşleriniz.
Ayman Mahgoub

2
Mesajımın yeterince açık olmadığını düşünüyorum. OnPreExecute () 'de iptal etmen gerektiğini söylemedim, onPreExecute ()' de İşleyiciyi oluşturman ve gecikmiş iptali ana iş parçacığından göndermen gerektiğini söyledim. Bu şekilde ana iş parçacığını döngüleyici iş parçacığı olarak kullanacaksınız ve tabii ki daha sonra doInBackground () çalışırken AsyncTask'ı iptal edebilirsiniz çünkü ana iş parçacığı arka plan iş parçacığı ile aynı anda çalışır.
BladeCoder

-1

Basit bir satır ekleyerek böyle benzer bir soruna çözüm bulabilirim

HttpURLConnection hConn = (HttpURLConnection) url.openConnection();
hConn.setRequestMethod("HEAD");

Benim ihtiyacım yanıt kodunu bilmekti ve bunun için tam yanıt gövdesini almak yerine sadece meta bilgileri almak yeterliydi.

Varsayılan istek yöntemi GET'tir ve geri dönmesi çok zaman alıyordu, sonunda bana SocketTimeoutException atılıyor. İstek Yöntemini HEAD olarak ayarladığımda yanıt oldukça hızlıydı.


1
Bu hiçbir şekilde çözüm değil, istek yöntemini HEADherhangi bir yanıt gövdesi üretmeyecek bir isteğe değiştiriyorsunuz .
Sveinung Kval Bakken

Bu, orijinal soruya hiçbir şey eklemez. OP'nin .setRequestMethod("HEAD")kodunda vardır. İşin garibi, bu açıklama "Çok fazla açık dosya" sorunumu azaltmak için tam da ihtiyacım olan şeydi. Yani teşekkürler?
Joshua Pinter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.