关于 url:如何根据 Java 中的 URLConnection 对 BufferedReader 设置超时?

关于 url:如何根据 Java 中的 URLConnection 对 BufferedReader 设置超时?

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

我想读取 URL 的内容,但不想在 URL 无响应时"挂起"。我使用 URL 创建了一个 BufferedReader...

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

...然后开始循环读取内容...

1
2
3
4
5
6
7
8
9
10
11
do
    {
    buf = urlReader.readLine();
    if (buf != null)
        {
        resultBuffer.append(buf);
        resultBuffer.append("\
"
);
        }
    }
while (buf != null);

...但如果读取挂起,则应用程序挂起。

有没有一种方法,无需将代码打磨到套接字级别,在必要时"超时"读取?


我认为 URLConnection.setReadTimeout 是您正在寻找的。


如果你有 java 1.4:

我认为连接超时 (URLConnection.setConnectTimeout(int timeout) ) 没有用,因为您正在执行某种流式传输。

---不杀线程---可能会导致未知问题,打开描述符等

生成一个 java.util.TimerTask,您将在其中检查是否已完成该过程,否则,关闭 BufferedReader 和 URLConnection 的 OutputStream

插入一个布尔标志 isFinished 并在循环结束时将其设置为 true,在循环之前将其设置为 false

1
2
3
4
5
6
7
8
9
10
TimerTask ft = new TimerTask(){
   public void run(){
     if (!isFinished){
       urlConn.getInputStream().close();
      urlConn.getOutputStream().close();
     }
   }
};

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

这可能会导致 ioexception,所以你必须抓住它。例外本身并不是一件坏事。
我省略了一些声明(即决赛),因此匿名类可以访问您的变量。如果没有,则创建一个维护引用的 POJO 并将其传递给 timertask


从 Java 1.5 开始,可以通过 URLConnection 类上的 'setReadTimeout(int timeout)' 方法在底层套接字上设置读取超时(以毫秒为单位)。

请注意,还有 'setConnectTimeout(int timeout)' 将对与远程服务器的初始连接执行相同的操作,因此设置它也很重要。


对于 Java 1.4,您可以使用来自 Apache

的 SimpleHttpConnectionManager.getConnectionWithTimeout(hostConf,CONNECTION_TIMEOUT)


我最近一直在 JVM 1.4 环境中处理这个问题。常用的答案是使用系统属性 sun.net.client.defaultReadTimeout(读取超时)和/或 sun.net.client.defaultConnectTimeout。这些记录在 Networking Properties 中,可以通过 Java 命令行上的 -D 参数或通过 System.setProperty 方法调用进行设置。

假设这些是由实现缓存的,因此您不能将它们从一种事物更改为另一种事物,因此它们被使用一次,值将被保留。

它们也不适用于 SSL 连接 ala HttpsURLConnection。还有其他方法可以使用自定义 SSLSocketFactory.

同样,这一切都适用于 JVM 1.4.x。在 1.5 及更高版本中,您可以在 API 中使用更多方法(如上述其他响应者所述)。


推荐阅读