15

我有以下代码块:

try {
    URL url = new URL("http://site-to-test.com/nonexistingpage.html");

    HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
    urlc.setRequestProperty("User-Agent", CoreProtocolPNames.USER_AGENT);
    urlc.setRequestProperty("Connection", "close");
    urlc.setConnectTimeout(500); // timeout is in milliseconds
    urlc.connect();

    if (urlc.getResponseCode() == 404) {
        // Server was reachable
        Log.i(TAG, "Server is reachable");
    }

} catch (MalformedURLException mue) {
    Log.e(TAG, "MalformedURLException: " + mue.getMessage());
} catch (IOException e) {
    Log.e(TAG, "IOException: " + e.getMessage());
}

site-to-test通过当前网络无法访问域时,此代码会阻塞大约 30-40 秒,然后才会收到IOException. 我特意将超时值设置为 500ms。我在这里想念什么?无论网络状态和站点的可用性如何,上述块不应该在半秒内终止吗?

4

2 回答 2

14

Java URLConnection似乎在读取时没有提供故障安全超时

正如文章所解释的,解决方案是使用单独的线程进行计时,并在计时器线程完成后手动断开 HttpURLConnection。

于 2012-07-04T14:15:02.397 回答
1

经过深入调查和大量跟踪,我发现为 AsyncTask(或服务,您用来执行后台工作的对象)实现计时器的最佳方法远离 HTTP 连接类,有时当您断开 HTTP 连接时,这不会中断网络调用,我实现了这个类,当你需要超时检查你的 HTTP 连接时使用

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;
    };
 }
于 2014-12-22T09:26:27.707 回答