How can I set a timeout against a BufferedReader b

2019-01-26 08:45发布

问题:

I want to read the contents of a URL but don't want to "hang" if the URL is unresponsive. I've created a BufferedReader using the URL...

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?

回答1:

I think URLConnection.setReadTimeout is what you are looking for.



回答2:

If you have java 1.4:

I assume the connection timeout (URLConnection.setConnectTimeout(int timeout) ) is of no use because you are doing some kind of streaming.

---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

Insert a boolean flag isFinished and set it to true at the end of your loop and to false before the loop

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. The exception is not a bad thing in itself. I'm omitting some declarations (i.e. 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



回答3:

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.

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.



回答4:

I have been working on this issue in a JVM 1.4 environment just recently. The stock answer is to use the system properties sun.net.client.defaultReadTimeout (read timeout) and/or 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.

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. There are other ways to deal with that using a custom SSLSocketFactory.

Again, all this applies to 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).



回答5:

For Java 1.4, you may use SimpleHttpConnectionManager.getConnectionWithTimeout(hostConf,CONNECTION_TIMEOUT) from Apache



标签: java url sockets