2010-05-10 161 views
91

我想要返回false如果URL需要超过5秒的连接 - 这怎么可能使用Java?下面是我使用的检查网址是否有效HttpURLConnection超时设置

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

回答

153

HttpURLConnectionsetConnectTimeout方法的代码。

超时正好被设置为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; 
} 

 
+1

我将该值设置为10分钟。然而,在2分钟之前,它会抛出一个'java.net.ConnectException:Connection超时:connect'。你知道是什么导致了这个问题? – Pacerier 2012-02-03 10:16:32

+0

@dbyrne这对我来说似乎有点困惑 - 因为我们在创建HttpURLConnection对象后设置了超时时间,所以我想知道代码中引发'SocketTimeoutException'的确切位置是什么? – Less 2013-07-24 16:57:36

+3

SocketTimeoutException是IOException的子类。如果两个catch块都执行相同的操作,则可以捕获IOException。 – spaaarky21 2013-12-05 22:27:01

85

您可以设置超时这样,

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

什么是我们可以指定的超时的最大值? – Pacerier 2012-02-03 10:16:48

+5

@Pacerier文档没有明确说明这一点。如果值为负数(值为0意味着无限期地等待),它会抛出IllegalArgumentException异常。由于超时是一个无符号的32位整数,我想最大超时大概是49天(尽管我严重怀疑这个值对任何人都有帮助)。 – 2012-10-25 07:17:06

+1

+1为多种类型的超时... – jsh 2012-12-26 16:54:19

1

如果HTTP连接不超时,你可以在后台线程本身(AsyncTask,Service等)中实现超时检查器,下面的类是考试PLE为自定义的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; 
    }; 
} 
+0

创建一个新的循环线程是绝对没有必要安排一个调用取消()。你可以在'onPreExecute()'的主线程中做到这一点。另外,如果您手动取消任务,则还应取消预定的呼叫以避免泄漏。 – BladeCoder 2015-09-30 07:44:43

+0

这里指的是在doInBackground()中间取消AsyncTask,而不是在执行onPreExecute()时需要太多时间,同样我想取消AsyncTask的这个实例,这需要花费太多时间并且保留其他的很多感谢您的反馈。 – 2015-09-30 12:03:20

+1

我觉得我的信息不够清楚。我没有说你应该取消onPreExecute(),我说你应该在onPreExecute()中创建Handler,并从主线程发布延迟取消。这样您将使用主线程作为循环线程,并且当doInBackground()正在执行时,您当然可以取消AsyncTask,因为主线程也与后台线程同时运行。 – BladeCoder 2015-09-30 12:36:47

0

样我能得到解决这样类似的问题,另外一个简单的线条

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

后超时我要求是知道响应代码,并且只是获取元信息就足够了,而不是获得完整的响应主体。

默认的请求方法是GET,那需要很多时间才能返回,最后抛出SocketTimeoutException。当我将请求方法设置为HEAD时,响应非常快。