简体   繁体   English

如何根据Java中的URLConnection对BufferedReader设置超时?

[英]How can I set a timeout against a BufferedReader based upon a URLConnection in Java?

I want to read the contents of a URL but don't want to "hang" if the URL is unresponsive. 我想读取URL的内容,但如果URL没有响应则不想“挂起”。 I've created a BufferedReader using the URL... 我使用URL创建了一个BufferedReader ...

URL theURL = new URL(url);
URLConnection urlConn = theURL.openConnection();
urlConn.setDoOutput(true);
BufferedReader urlReader = new BufferedReader(newInputStreamReader(urlConn.getInputStream()));

...and then begun the loop to read the contents... ...然后开始循环阅读内容......

do
    {
    buf = urlReader.readLine();
    if (buf != null)
        {
        resultBuffer.append(buf);
        resultBuffer.append("\n");
        }
    }
while (buf != null);

...but if the read hangs then the application hangs. ...但如果读取挂起,则应用程序挂起。

Is there a way, without grinding the code down to the socket level, to "time out" the read if necessary? 有没有办法,如果没有将代码磨到套接字级别,必要时“超时”读取?

我认为URLConnection.setReadTimeout就是你要找的东西。

If you have java 1.4: 如果你有java 1.4:

I assume the connection timeout ( URLConnection.setConnectTimeout(int timeout) ) is of no use because you are doing some kind of streaming. 我假设连接超时( URLConnection.setConnectTimeout(int timeout) )是没有用的,因为你正在做某种流式传输。

--- Do not kill the thread --- It may cause unknown problems, open descriptors, etc. --- 不要杀死线程 ---可能会导致未知问题,打开描述符等。

Spawn a java.util.TimerTask where you will check if you have finished the process, otherwise, close the BufferedReader and the OutputStream of the URLConnection 生成java.util.TimerTask,您将检查是否已完成该过程,否则,关闭URLConnection的BufferedReader和OutputStream

Insert a boolean flag isFinished and set it to true at the end of your loop and to false before the loop 插入一个布尔标志isFinished并在循环结束时将其设置为true,并在循环之前将其设置为false

TimerTask ft = new TimerTask(){
   public void run(){
     if (!isFinished){
       urlConn.getInputStream().close();
      urlConn.getOutputStream().close();
     }
   }
};

(new Timer()).schedule(ft, timeout);

This will probably cause an ioexception, so you have to catch it. 这可能会导致ioexception,所以你必须抓住它。 The exception is not a bad thing in itself. 这个例外本身并不是一件坏事。 I'm omitting some declarations (ie finals) so the anonymous class can access your variables. 我省略了一些声明(即决赛),所以匿名类可以访问你的变量。 If not, then create a POJO that maintains a reference and pass that to the timertask 如果没有,则创建一个维护引用的POJO并将其传递给timertask

Since Java 1.5, it is possible to set the read timeout in milliseconds on the underlying socket via the 'setReadTimeout(int timeout)' method on the URLConnection class. 从Java 1.5开始,可以通过URLConnection类上的'setReadTimeout(int timeout)'方法在底层套接字上设置读取超时(以毫秒为单位)。

Note that there is also the 'setConnectTimeout(int timeout)' which will do the same thing for the initial connection to the remote server, so it is important to set that as well. 请注意,还存在'setConnectTimeout(int timeout)',它将对远程服务器的初始连接执行相同的操作,因此设置它也很重要。

对于Java 1.4,您可以使用Apache的SimpleHttpConnectionManager.getConnectionWithTimeout(hostConf,CONNECTION_TIMEOUT)

I have been working on this issue in a JVM 1.4 environment just recently. 我最近刚刚在JVM 1.4环境中研究过这个问题。 The stock answer is to use the system properties sun.net.client.defaultReadTimeout (read timeout) and/or sun.net.client.defaultConnectTimeout. 库存答案是使用系统属性sun.net.client.defaultReadTimeout(读取超时)和/或sun.net.client.defaultConnectTimeout。 These are documented at Networking Properties and can be set via the -D argument on the Java command line or via a System.setProperty method call. 这些在Networking Properties中记录 ,可以通过Java命令行上的-D参数或通过System.setProperty方法调用进行设置。

Supposedly these are cached by the implementation so you can't change them from one thing to another so one they are used once, the values are retained. 据推测,这些都是由实现缓存的,所以你不能将它们从一个东西改为另一个东西,所以一次使用它们,值就会被保留。

Also they don't really work for SSL connections ala HttpsURLConnection. 此外,它们并不适用于SSL连接和HttpsURLConnection。 There are other ways to deal with that using a custom SSLSocketFactory. 还有其他方法可以使用自定义SSLSocketFactory来处理它。

Again, all this applies to JVM 1.4.x. 同样,所有这些都适用于JVM 1.4.x. At 1.5 and above you have more methods available to you in the API (as noted by the other responders above). 在1.5及以上,您可以在API中使用更多方法(如上面其他响应者所述)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM