HttpURLConnection setConnectTimeout()无效

时间:2011-07-26 12:11:36

标签: java android

我正在使用HTTPUrlConnection连接到简单的RSS提要。它完美地运作。我想在连接中添加超时,因为我不希望我的应用程序在连接错误或其他情况下挂起。这是我使用的代码,setConnectTimeout方法没有任何效果。

        HttpURLConnection http = (HttpURLConnection) mURL.openConnection();
        http.setConnectTimeout(15000); //timeout after 15 seconds
...

如果它有助于我在Android上开发。

8 个答案:

答案 0 :(得分:57)

您也应该尝试设置读取超时(http.setReadTimeout())。通常情况下,Web服务器会很乐意接受您的连接,但实际响应请求可能会很慢。

答案 1 :(得分:16)

你可能要么/两个:
1)请勿阅读连接中的任何内容 2)不要抓住&正确处理异常

如上所述here,请使用与此类似的逻辑:

int TIMEOUT_VALUE = 1000;
try {
    URL testUrl = new URL("http://google.com");
    StringBuilder answer = new StringBuilder(100000);

    long start = System.nanoTime();

    URLConnection testConnection = testUrl.openConnection();
    testConnection.setConnectTimeout(TIMEOUT_VALUE);
    testConnection.setReadTimeout(TIMEOUT_VALUE);
    BufferedReader in = new BufferedReader(new InputStreamReader(testConnection.getInputStream()));
    String inputLine;

    while ((inputLine = in.readLine()) != null) {
        answer.append(inputLine);
        answer.append("\n");
    }
    in.close();

    long elapsed = System.nanoTime() - start;
    System.out.println("Elapsed (ms): " + elapsed / 1000000);
    System.out.println("Answer:");
    System.out.println(answer);
} catch (SocketTimeoutException e) {
    System.out.println("More than " + TIMEOUT_VALUE + " elapsed.");
}

答案 2 :(得分:6)

我有类似的问题 - 因为HttpUrlConnection won't time out中期下载。例如,如果您在下载时关闭wifi,我的继续说它正在下载,卡在相同的百分比。

我找到了一个解决方案,使用TimerTask连接到名为DownloaderTask的AsyncTask。尝试:

class Timeout extends TimerTask {
    private DownloaderTask _task;

    public Timeout(DownloaderTask task) {
        _task = task;
    }

    @Override
    public void run() {
        Log.w(TAG,"Timed out while downloading.");
        _task.cancel(false);
    }
};

然后在实际的下载循环中设置超时错误的计时器:

                    _outFile.createNewFile();
                    FileOutputStream file = new FileOutputStream(_outFile);
                    out = new BufferedOutputStream(file);
                    byte[] data = new byte[1024];
                    int count;
                    _timer = new Timer();
                    // Read in chunks, much more efficient than byte by byte, lower cpu usage.
                    while((count = in.read(data, 0, 1024)) != -1 && !isCancelled()) { 
                        out.write(data,0,count);
                        downloaded+=count;
                        publishProgress((int) ((downloaded/ (float)contentLength)*100));
                        _timer.cancel();
                        _timer = new Timer();
                        _timer.schedule(new Timeout(this), 1000*20);
                    }
                    _timer.cancel();
                    out.flush();

如果超时,并且在20秒内不会下载1K,则取消而不是永远下载。

答案 3 :(得分:4)

我遇到了同样的问题。设置connectionTimeoutreadTimeout似乎并没有像预期的那样返回异常,但确实如此。我花了很长时间检查URLConnection()方法并了解发生了什么。在setConnectTimeout的文档中有一个警告

“如果主机名解析为多个IP地址,则此客户端将尝试各自。如果连接到这些地址中的每一个都失败,则在连接尝试引发异常之前将经过多次超时。”   这意味着如果您的主机解决了10个ips,您的实际时间将为“10 * readTimeoutSet”。

您可以检查主机名here

的ips

答案 4 :(得分:3)

http.setConnectTimeout(15000);
http.setReadTimeout(15000);

答案 5 :(得分:0)

原因是:
1.您已连接到wifi,但没有互联网连接。
2.您已连接到GSM数据,但传输非常差。

在两种情况下,您都会在大约20秒后收到主机异常。我认为正确的最佳方法是:

public boolean isOnline() {
        final int TIMEOUT_MILLS = 3000;
        final boolean[] online = {false};
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) {
            final long time = System.currentTimeMillis();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        URL url = new URL("http://www.google.com");
                        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
                        urlc.setConnectTimeout(TIMEOUT_MILLS);
                        urlc.setReadTimeout(TIMEOUT_MILLS);
                        urlc.connect();
                        if (urlc.getResponseCode() == 200) {
                            online[0] = true;
                        }
                    } catch (IOException e) {
                        loger.add(Loger.ERROR, e.toString());
                    }
                }
            }).start();

            while (((System.currentTimeMillis() - time) <= TIMEOUT_MILLS)) {
                if ((System.currentTimeMillis() - time) >= TIMEOUT_MILLS) {
                    return online[0];
                }
            }
        }
        return online[0];
    }

记住-在异步任务或服务中使用它。

它是简单的解决方案,您正在使用HttpUrlConnection启动新线程(请记住使用start()而不是run())。比while循环,您要等待3秒钟才能得到结果。如果没有任何反应,则返回false。这样一来,您可以避免等待主机异常,并避免在没有Internet连接时无法运行setConnectTimeout()的问题。

答案 6 :(得分:0)

零值表示无限期超时,这意味着必须建立连接并且通常默认为零:

connection.setConnectTimeout(0);
connection.setReadTimeout(0);

参阅here

答案 7 :(得分:-2)

尝试在打开连接之前设置ConnectionTimeout