在响应完成之前关闭HttpURLConnection

时间:2011-11-27 06:28:00

标签: java httpurlconnection

背景

我在客户端使用HttpURLConnection来消费HTTP流(服务器推送)情况下的响应。虽然服务器可以通过关闭响应来关闭连接,但客户端也需要能够执行此操作。

问题

客户端在单独的线程中处理InputStream,如下所示:

@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) {
    }
}

因此,当我从发起连接的线程中调用HttpURLConnection.disconnect()时(重要的信息是它与处理输入的线程不同),该调用将无限期挂起。我甚至把它留在了一夜之间它仍然悬挂着。即使致电Thread.interrupt()也无济于事。

建议?

3 个答案:

答案 0 :(得分:5)

如果没有改变读取线程使用InputStream.available()进行轮询并且在没有可用字节的情况下睡眠很短的时间,看起来这样做是不可能的,同时检查一些标志以查看线程是否应该端。

解决方案是使用Apache HTTP Components。通过将GET请求的代码封装在一个类中,可以很容易地将其集成到现有代码中。

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

原始帖子中的循环可以保持原样,并且在调用HttpGetConnection.close()后,阅读主题将很快死亡。

答案 1 :(得分:1)

如果服务器未关闭连接但停止发送数据,in.read()将阻止。现在,请注意HttpURLConnection.HttpInputStream.close()的代码将尝试从流中读取以确定到达流的末尾(source code)。 反过来,close()来自disconnect()。最终你的线程被阻止了。

所以看来你需要改变你的逻辑。我假设您根据某些条件关闭连接。因此,在读取线程中读取下一个字节之前,不要在不同的线程中检查条件,然后断开连接。

顺便说一下,Thread.interrupt()不会帮助你,因为它只会在你的等待IO时中断在监视器上等待的线程。

答案 2 :(得分:0)

另一种解决方法是将输入流包装在Channel中并使用该{({1}}),如JDK-4329256的变通方法中所建议的那样。这将导致在线程中断时关闭底层输入流。但是,JDK中有一条评论说它不是真正可以中断的。在我的测试中它似乎工作。我已经向here询问了更多信息。

相关问题