Java URLConnection 超时时间

66

我正在尝试从HTTP URL解析XML文件。如果XML获取时间超过15秒,我想配置一个超时,并报告超时。但是由于某种原因,setConnectTimeout和setReadTimeout不起作用。以下是代码:

          URL url = new URL("http://www.myurl.com/sample.xml");
          URLConnection urlConn = url.openConnection();
          urlConn.setConnectTimeout(15000);
          urlConn.setReadTimeout(15000);
          urlConn.setAllowUserInteraction(false);         
          urlConn.setDoOutput(true);

          InputStream inStream = urlConn.getInputStream();
          InputSource input = new InputSource(inStream);

我正在捕获SocketTimeoutException异常。

谢谢 Chris


它是否挂起?发生了什么事?你正在从流中读取吗? - Marcus Adams
不,它不会挂起,也没有异常。在解析后,我的变量只是空的。 - Chris
3
请让我们看更多的代码。 - Marcus Adams
你解决了这个问题吗?我也遇到了同样的问题。 - Andreas Mattisson
1
这不是它的工作方式。读取超时只影响单个读取,而不是总读取时间。你的代码在哪里? - user207421
5个回答

32

试试这个:

       import java.net.HttpURLConnection;

       URL url = new URL("http://www.myurl.com/sample.xml");

       HttpURLConnection huc = (HttpURLConnection) url.openConnection();
       HttpURLConnection.setFollowRedirects(false);
       huc.setConnectTimeout(15 * 1000);
       huc.setRequestMethod("GET");
       huc.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)");
       huc.connect();
       InputStream input = huc.getInputStream();

OR

       import org.jsoup.nodes.Document;

       Document doc = null;
       try {
           doc = Jsoup.connect("http://www.myurl.com/sample.xml").get();
       } catch (Exception e) {
           //log error
       }

并学习如何使用Jsoup:http://jsoup.org/cookbook/input/load-document-from-url


1
使用Java 7(+)时,它的工作方式与预期相同:conn.setReadTimeout(1000*10*1); conn.setConnectTimeout(1000*10*1); //等待连接的10秒 等待连接和数据的确切时间为10秒。 - Axel Amthor
3
这只影响连接超时,不影响读取超时。并没有以任何方式回答问题。 - user207421

19

您可以通过线程休眠来强制手动断开连接。以下是一个示例:

URLConnection con = url.openConnection();
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
new Thread(new InterruptThread(con)).start();

然后

public class InterruptThread implements Runnable {

    HttpURLConnection con;
    public InterruptThread(HttpURLConnection con) {
        this.con = con;
    }

    public void run() {
        try {
            Thread.sleep(5000); // or Thread.sleep(con.getConnectTimeout())
        } catch (InterruptedException e) {

        }
        con.disconnect();
        System.out.println("Timer thread forcing to quit connection");
    }
}

从文档中:void java.net.HttpURLConnection.disconnect()表示在不久的将来不太可能向服务器发出其他请求。调用disconnect()不应意味着此HttpURLConnection实例可以重用于其他请求。因此,在调用disconnect()时套接字未必关闭。 - A.G.
3
请注意,即使您成功连接并希望继续使用该连接,此代码也会在5秒钟内尝试断开连接。 - Fyodor Menshikov

14

您可以通过更改以下系统属性为JVM中的所有连接设置超时时间:

System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");

每个连接将在10秒后超时。

设置"defaultReadTimeout"不是必需的,但如果您需要控制阅读,则可以将其作为示例显示。


这就是我需要的,以便在Windows和OSX上都能正常工作。 - Allison
仅适用于HTTP。java.net.Socket不使用这些。 - user207421

9

我曾经使用类似的代码从服务器下载日志。我调试了一下我的代码,发现返回的URLConnection实现是sun.net.www.protocol.http.HttpURLConnection。

抽象类java.net.URLConnection有两个属性connectTimeout和readTimeout,并且setter在抽象类中。信不信由你,sun.net.www.protocol.http.HttpURLConnection实现也有相同的属性connectTimeout和readTimeout,但没有setter,而且在getInputStream方法中使用来自实现类的属性。因此,在设置connectTimeout和readTimeout时没有用处,因为它们在getInputStream方法中从未被使用。在我看来,这是sun.net.www.protocol.http.HttpURLConnection实现中的一个bug。

我的解决方案是使用HttpClient和Get请求。


3
尽管这可能取决于Java版本,但Java 6.0 API表明:“某些非标准实现方法会忽略指定的超时时间。要查看读取超时设置,请调用getReadTimeout()方法。”(http://docs.oracle.com/javase/6/docs/api/java/net/URLConnection.html#setReadTimeout(int)) - David O'Meara
这两个属性在我身上已经发挥了20多年的作用。 - user207421

1

1
自1992年以来就没有见过这种情况。你的链接中也没有提供任何证据。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接