Close the HttpURLC connection before completing the response

Background

I am using HttpURLConnection on the client side to use the response in an HTTP streaming stream. Although the server can close the connection by closing the response, it is also necessary that the client can do this.

Problem

The client processes the InputStream in a separate stream, for example:

 @Override public void run() { try { for (int b = in.read(); b >= 0; b = in.read()) { char c = (char) b; // Do something with the character // ... } } catch (IOException e) { } } 

Therefore, when I call HttpURLConnection.disconnect() from the thread that initiated the connection (an important part of the information is that it is a different thread from the one that processes the input), this call hangs indefinitely. I even left it for the night, and it was still hanging. Even calling Thread.interrupt() did not help.

Suggestions?

+6
source share
3 answers

It seems like this cannot be done without changing the read stream for polling, using InputStream.available() and sleeping for a short period when there are no bytes, checking some flag all the time to see if the stream should end.

The solution is to simply use the Apache HTTP components. By encapsulating the code for a GET request within one class, it can be easily integrated into existing code.

 public class HttpGetConnection implements AutoCloseable { public HttpGetConnection(String url) throws IOException { client = new DefaultHttpClient(); get = new HttpGet(url); response = client.execute(get); entity = response.getEntity(); } public InputStream getContent() throws IOException { content = entity.getContent(); return content; } @Override public void close() throws Exception { get.abort(); try { content.close(); } catch (IOException e) { } } private HttpClient client; private HttpGet get; private HttpResponse response; private HttpEntity entity; private InputStream content; } 

The loop in the source column may remain as it is, and the read stream will die soon after calling HttpGetConnection.close() .

+4
source

If the server does not close the connection but stops sending data, in.read() will block. Now notice that the code for HttpURLConnection.HttpInputStream.close() will also try to read from the stream to determine if the end of the stream has been reached ( source code) , close() , in turn, is called from disconnect() . And in the end, you blocked your threads.

So you need to change your logic. I assume that you are closing the connection based on some conditions. Therefore, instead of doing this in different threads, check the conditions before reading the next byte in the read stream, and then turn it off.

And by the way, Thread.interrupt() will not help you, since it will only interrupt threads waiting on monitors while your is waiting in IO.

+1
source

Another workaround is to wrap the input stream in the channel and use this ( Channels.newChannel ), as suggested in the JDK-4329256 workaround . This will cause the main input stream to be closed when the stream is interrupted. However, there is a comment in the JDK that it really does not interrupt. In my testing, this works. I asked here for more information.

0
source

Source: https://habr.com/ru/post/902472/


All Articles