Cài đặt thời gian chờ kết nối httpURLC


123

Tôi muốn trả về false nếu URL mất hơn 5 giây để kết nối - làm thế nào điều này có thể sử dụng Java? Đây là mã tôi đang sử dụng để kiểm tra xem URL có hợp lệ không

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

Câu trả lời:


201

HttpURLConnectioncó một phương thức setConnectTimeout .

Chỉ cần đặt thời gian chờ là 5000 mili giây, sau đó bắt java.net.SocketTimeoutException

Mã của bạn sẽ trông giống như thế này:


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
Tôi đặt giá trị thành 10 phút. Tuy nhiên, nó ném cho tôi java.net.ConnectException: Connection timed out: connecttrước khi thậm chí 2 phút là hết. Bạn có biết những gì gây ra vấn đề?
Pacerier

5
SocketTimeoutException là một lớp con của IOException. Nếu cả hai khối bắt đều làm điều tương tự, bạn có thể bắt IOException.
spaaarky21

2
@ spaaarky21 là chính xác. Tuy nhiên, nếu bạn đang xây dựng một giao diện người dùng và bạn muốn thông báo cho người dùng của mình rằng đã hết thời gian chờ, bạn phải bắt được SocketTimeoutException trước IOException, nếu không, nó sẽ không thể truy cập được.
clocker

3
Lưu ý !!! bạn cần gọi setConnectTimeouttrước bất kỳ phương thức nào kết nối ngầm (về cơ bản tất cả các phương thức ném IllegalStateException nếu đã được kết nối). Lý tưởng nhất là đặt setConnectTimeout (readTimeout) các phương thức đầu tiên được gọi.
Adam Gent

4
Nó không làm việc cho tôi. Nhưng, sau khi thêm con.setReadTimeout(), nó hoạt động như mong đợi.
Paulo

115

Bạn có thể đặt thời gian chờ như thế này,

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

2
Giá trị tối đa của thời gian chờ chúng ta có thể chỉ định là gì?
Pacerier

7
@Pacerier Các tài liệu không nêu rõ điều này. Nó sẽ ném IllegalArgumentException nếu giá trị âm (giá trị 0 có nghĩa là chờ đợi vô thời hạn). Vì thời gian chờ là int 32 bit không dấu, tôi đoán thời gian chờ tối đa sẽ là khoảng 49 ngày (mặc dù tôi thực sự nghi ngờ rằng giá trị như vậy sẽ hữu ích cho bất kỳ ai).
Jay Sidri

1

Nếu Kết nối HTTP không hết thời gian, Bạn có thể triển khai trình kiểm tra thời gian chờ trong chính luồng nền (AsyncTask, Dịch vụ, v.v.), lớp sau đây là một ví dụ cho Tùy chỉnh AsyncTask sẽ hết thời gian sau một khoảng thời gian nhất định

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

Một mẫu cho điều này

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

Hoàn toàn không cần thiết để tạo một chuỗi looper mới chỉ để lên lịch cuộc gọi để hủy (). Bạn có thể làm điều đó từ chủ đề chính trong onPreExecute(). Ngoài ra, nếu bạn hủy tác vụ theo cách thủ công, bạn cũng nên hủy cuộc gọi theo lịch trình để tránh rò rỉ.
BladeCoder

Vấn đề ở đây là hủy AsyncTask ở giữa doInBackground () khi mất quá nhiều thời gian để thực thi không phải trên onPreExecute (), tôi cũng muốn hủy chỉ trường hợp này của AsyncTask, việc này mất quá nhiều thời gian và đánh giá cao những người khác, đánh giá cao thông tin phản hồi của bạn.
Ayman Mahgoub

2
Tôi nghĩ rằng thông điệp của tôi không đủ rõ ràng. Tôi không nói bạn nên hủy trong onPreExecute (), tôi đã nói bạn nên tạo Handler trong onPreExecute () và đăng việc hủy bị trì hoãn từ luồng chính. Bằng cách này, bạn sẽ sử dụng luồng chính làm luồng looper và dĩ nhiên bạn có thể hủy AsyncTask sau khi doInBackground () đang thực thi vì luồng chính cũng chạy đồng thời với luồng nền.
BladeCoder

-1

Tôi có thể có được giải pháp cho một vấn đề tương tự như vậy với việc thêm một dòng đơn giản

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

Yêu cầu của tôi là phải biết mã phản hồi và chỉ cần có được thông tin meta là đủ, thay vì nhận được phần phản hồi hoàn chỉnh.

Phương thức yêu cầu mặc định là GET và mất rất nhiều thời gian để trả về, cuối cùng ném cho tôi SocketTimeoutException. Phản hồi khá nhanh khi tôi đặt Phương thức yêu cầu thành CHÍNH.


1
Đây không phải là giải pháp theo bất kỳ cách nào, bạn đang thay đổi phương thức yêu cầu thành một HEADyêu cầu sẽ không tạo ra bất kỳ nội dung phản hồi nào.
Sveinung Kval Bakken

Điều này không thêm bất cứ điều gì vào câu hỏi ban đầu. OP có .setRequestMethod("HEAD")mã của họ. Điều kỳ lạ là mô tả này chính xác là những gì tôi cần để giảm vấn đề "Quá nhiều tệp đang mở". Vậy cảm ơn?
Joshua Pinter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.