HttpURLConnection 超时设置
Posted
技术标签:
【中文标题】HttpURLConnection 超时设置【英文标题】:HttpURLConnection timeout settings 【发布时间】:2011-02-17 12:01:32 【问题描述】:如果 URL 连接时间超过 5 秒,我想返回 false - 这怎么可能使用 Java?这是我用来检查 URL 是否有效的代码
HttpURLConnection.setFollowRedirects(false);
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
con.setRequestMethod("HEAD");
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
【问题讨论】:
【参考方案1】: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;
【讨论】:
我将值设置为 10 分钟。然而,它甚至在 2 分钟结束之前给我一个java.net.ConnectException: Connection timed out: connect
。你知道是什么导致了这个问题吗?
SocketTimeoutException 是 IOException 的子类。如果两个 catch 块做同样的事情,你可以只捕获 IOException。
@spaarky21 是正确的。但是,如果您正在构建 UI 并且想要通知用户发生超时,则必须在 IOException 之前捕获 SocketTimeoutException,否则将无法访问。
注意!!! 您需要在任何隐式连接的方法之前调用setConnectTimeout
(基本上是所有已连接时抛出 IllegalStateException 的方法)。理想情况下,首先调用 setConnectTimeout (readTimeout) 方法。
它对我不起作用。但是,添加con.setReadTimeout()
后,它按预期工作。【参考方案2】:
你可以这样设置超时,
con.setConnectTimeout(connectTimeout);
con.setReadTimeout(socketTimeout);
【讨论】:
我们可以指定的最大超时时间是多少? @Pacerier 文档没有明确说明这一点。如果值为负数(值为 0 表示无限期等待),它会抛出 IllegalArgumentException。由于超时是一个无符号的 32 位整数,我猜最大超时大约是 49 天(尽管我严重怀疑这个值对任何人都有帮助)。 我同时使用了超时,但仍然出现超时错误。但是当我检查日志时,我的请求需要 20 秒,但我给了 100 秒的 setConnectTimeout【参考方案3】:如果 HTTP 连接没有超时,您可以在后台线程本身(AsyncTask、Service 等)中实现超时检查器,以下类是自定义 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()的调用而创建一个新的looper线程。您可以从onPreExecute()
中的主线程执行此操作。另外,如果您手动取消任务,您还应该取消预定的调用以避免泄漏。
这里的要点是在 doInBackground() 中间取消 AsyncTask,因为它在执行而不是在 onPreExecute() 上花费了太多时间,我也想只取消这个 AsyncTask 的实例,这需要太多时间时间并保留其他人,非常感谢您的反馈。
我认为我的信息不够清楚。我没有说你应该在 onPreExecute() 中取消,我说你应该在 onPreExecute() 中创建处理程序并从主线程发布延迟取消。这样你就可以使用主线程作为 looper 线程,当然你可以在 doInBackground() 执行时取消 AsyncTask,因为主线程也和后台线程同时运行。【参考方案4】:
我可以通过添加一条简单的线来解决此类类似问题
HttpURLConnection hConn = (HttpURLConnection) url.openConnection();
hConn.setRequestMethod("HEAD");
我的要求是知道响应代码,因此仅获取元信息就足够了,而不是获取完整的响应正文。
默认的请求方法是 GET,这需要很长时间才能返回,最后抛出了 SocketTimeoutException。当我将请求方法设置为 HEAD 时,响应非常快。
【讨论】:
这绝不是解决方案,您将请求方法更改为HEAD
请求,它不会产生任何响应正文。
这不会对原始问题添加任何内容。 OP 在他们的代码中有.setRequestMethod("HEAD")
。奇怪的是,这个描述正是我减少“打开的文件太多”问题所需要的。那么谢谢?以上是关于HttpURLConnection 超时设置的主要内容,如果未能解决你的问题,请参考以下文章
HttpURLConnection.connect 卡死 死锁怎么解决
一定要为HttpUrlConnection设置connectTimeout属性以防止连接被阻塞