HttpURLConnection 시간 초과 설정


123

URL이 연결하는 데 5 초 이상 걸리면 false를 반환하고 싶습니다. Java를 사용하면 어떻게 가능합니까? URL이 유효한지 확인하는 데 사용하는 코드는 다음과 같습니다.

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

답변:


201

HttpURLConnection갖는다 setConnectTimeout의 방법.

시간 제한을 5000 밀리 초로 설정 한 다음 java.net.SocketTimeoutException

코드는 다음과 같아야합니다.


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
값을 10 분으로 설정했습니다. 그러나 그것은 java.net.ConnectException: Connection timed out: connect2 분도 다되기 전에 나를 던진다 . 문제의 원인을 알고 있습니까?
Pacerier

5
SocketTimeoutException은 IOException의 하위 클래스입니다. 두 catch 블록이 동일한 작업을 수행하면 IOException을 catch 할 수 있습니다.
spaaarky21

2
@ spaaarky21이 맞습니다. 그러나 UI를 빌드 중이고 시간 초과가 발생했음을 사용자에게 알리려면 IOException 전에 SocketTimeoutException을 잡아야합니다. 그렇지 않으면 도달 할 수 없습니다.
Clocker 2015

3
NB !!! setConnectTimeout암시 적으로 연결하는 메서드 (기본적으로 이미 연결된 경우 IllegalStateException을 throw하는 모든 메서드)보다 먼저 호출 해야합니다. 이상적으로는 setConnectTimeout (readTimeout)을 호출 된 첫 번째 메소드로 만드십시오.
Adam Gent

4
그것은 나를 위해 작동하지 않았습니다. 그러나을 추가하면 con.setReadTimeout()예상대로 작동했습니다.
Paulo

115

이렇게 시간 제한을 설정할 수 있습니다.

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

2
지정할 수있는 제한 시간의 최대 값은 얼마입니까?
Pacerier

7
@Pacerier 문서는 이것을 명시 적으로 언급하지 않습니다. 값이 음수이면 IllegalArgumentException이 발생합니다 (값 0은 무기한 대기를 의미 함). 시간 제한이 서명되지 않은 32 비트 정수이므로 최대 시간 제한은 약 49 일이 될 것이라고 생각합니다 (이러한 값이 누구에게나 도움이 될 것이라고 진지하게 의심하지만).
Jay Sidri 2010 년

1

HTTP Connection이 타임 아웃되지 않는 경우 백그라운드 쓰레드 자체 (AsyncTask, Service 등)에서 타임 아웃 검사기를 구현할 수 있으며, 다음 클래스는 특정 기간이 지나면 타임 아웃되는 Customize AsyncTask의 예입니다.

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

이에 대한 샘플

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

cancel () 호출을 예약하기 위해 새로운 루퍼 스레드를 만드는 것은 절대적으로 필요하지 않습니다. .NET의 기본 스레드에서 수행 할 수 있습니다 onPreExecute(). 또한 작업을 수동으로 취소하는 경우 누수를 방지하기 위해 예약 된 호출도 취소해야합니다.
BladeCoder

여기서 요점은 onPreExecute ()가 아닌 실행에 너무 많은 시간이 걸리면 doInBackground () 중간에 AsyncTask를 취소하는 것입니다. 또한 너무 많은 시간이 걸리는 AsyncTask의 인스턴스 만 취소하고 다른 인스턴스를 유지하고 싶습니다. 귀하의 의견.
Ayman Mahgoub 2015 년

2
내 메시지가 충분히 명확하지 않은 것 같습니다. 나는 당신이 onPreExecute ()에서 취소해야한다고 말하지 않았고, onPreExecute ()에서 Handler를 생성하고 메인 스레드에서 지연된 취소를 게시해야한다고 말했습니다. 이렇게하면 메인 스레드를 루퍼 스레드로 사용할 수 있으며, 메인 스레드도 백그라운드 스레드와 동시에 실행되기 때문에 doInBackground ()가 실행되는 동안 나중에 AsyncTask를 취소 할 수 있습니다.
BladeCoder 2015 년

-1

간단한 줄을 추가하면 비슷한 문제에 대한 해결책을 얻을 수 있습니다.

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

내 요구 사항은 응답 코드를 아는 것이었고 완전한 응답 본문을 얻는 대신 메타 정보를 얻는 것으로 충분했습니다.

기본 요청 방법은 GET이며 반환하는 데 많은 시간이 걸리고 마침내 SocketTimeoutException이 발생했습니다. 요청 방법을 HEAD로 설정했을 때 응답이 매우 빠릅니다.


1
이것은 어떤 식 으로든 해결책이 아니며 요청 방법을 HEAD응답 본문을 생성하지 않는 요청으로 변경합니다 .
Sveinung Kval Bakken

이것은 원래 질문에 아무것도 추가하지 않습니다. OP는 .setRequestMethod("HEAD")코드에 있습니다. 이상하게도이 설명은 "열린 파일이 너무 많음"이라는 문제를 줄이는 데 정확히 필요했습니다. 감사합니다?
여호수아 핀터
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.