[英]Closing an HttpURLConnection before the response is complete
我在客戶端使用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()
也無濟於事。
建議?
看起來如果不改變讀取線程使用InputStream.available()
進行輪詢,並且在沒有可用字節的情況下休眠一段短的perdiod,一直檢查一些標志以查看線程是否應該結束。
解決方案是僅使用Apache HTTP組件。 通過將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()
之后,讀取線程將很快死亡。
如果服務器沒有關閉連接但停止發送數據, in.read()
將阻止。 現在,請注意HttpURLConnection.HttpInputStream.close()
的代碼也將嘗試從流中讀取以確定到達流的末尾( 源代碼) 。 反過來, close()
從disconnect()
調用。 最終你的線程被阻止了。
所以你似乎需要改變你的邏輯。 我假設您根據某些條件關閉連接。 因此,在讀取線程中讀取下一個字節之前,不要在不同的線程中檢查條件,然后斷開連接。
順便說一句, Thread.interrupt()
不會幫助你,因為它只會在你的等待IO時中斷在監視器上等待的線程。
另一種解決方法是將輸入流包裝在Channel中並使用它( Channels.newChannel
),如JDK-4329256的變通方法中所建議的那樣 。 這將導致在線程中斷時關閉底層輸入流。 但是,JDK中有一條評論說它不是真正可以中斷的。 在我的測試中它似乎工作。 我在這里要求了解更多信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.