How to kill a BufferedInputStream .read() call

心不动则不痛 提交于 2019-12-04 04:20:14

问题


I'm working on writing a program to download very large files (~2GB) from a server. I've written the program to be able to resume partially finished downloads,

In order to simulate a bad internet connection, I've been pulling my ethernet cord out of my router while mid-download. Unfortunately, this causes my program to hang on the following call: while((bytesRead = in.read(data)) > 0)

(Where bytesRead is an int, in is a BufferedInputStream built from an HttpURLConnection, and data is a byte array).

I've tried to "interrupt" the call by calling in.close() on another thread, but it has no effect until the internet connection is restored (at which time an exception is thrown).

Is there any way I can prevent a severed internet connection from freezing my program?


回答1:


The only reliable way I found is to instantiate Socket as an InterruptibleChannel, and do an interrupt on a stuck IO thread. (BTW, you don't have to use asynchronous NIO calls with InterruptibleChannels, blocking I/O works fine, you just have a really nice and uniform way of kicking the stuck exchanges)

Though, it looks like URLConnection does not allow you to hook up a custom Socket factory.

Maybe you should investigate HttpClient from Apache.

EDIT

Here is how you create Interruptible Socket.

import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.channels.SocketChannel;

final SocketAddress remoteAddr =
    new InetSocketAddress(
        serverAddress,
        servicePort
    );

final SocketChannel socketChannel = SocketChannel.open( );

socketChannel.connect( remoteAddr );

// Here java.io.Socket is obtained
Socket socket = socketChannel.socket( );

I don't have HttpClient sample, but I know that you can customize socket initialization.




回答2:


See http://thushw.blogspot.com/2010/10/java-urlconnection-provides-no-fail.html for code to handle this situation

Edited: actually, setting a Socket timeout (in milliseconds) using setSoTimeout (as suggested in the link comment from Joop Eggen) is probably better.




回答3:


Have you .setReadTimeout(int timeout) on your URLConnection?

-- EDIT

See answer from @DNA for a neat solution:

in short words you can spawn a parallel thread that .disconnect()s the URLConnection (after letting your second thread sleep for timeout milliseconds), thus triggering an IOException that'll get you out of the stalled read.



来源:https://stackoverflow.com/questions/9041490/how-to-kill-a-bufferedinputstream-read-call

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!