如何解决读取无线电流时关闭 InputStream 挂起
我正在使用 Apache HttpClient 从无线电流中获取元数据。我想要做的是发出 GET 请求,读取一些字节然后关闭流。对于某些流,它可以正常工作,但对于其他一些流,流的关闭会挂起。看起来它仍在接收数据并且在它发生时没有关闭连接。
public SongInfo retrieveMetadata(String streamUrl) {
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(streamUrl);
httpGet.addHeader("Icy-MetaData","1");
httpGet.addHeader("Connection","close");
httpGet.addHeader("Accept","");
HttpResponse response;
try {
response = httpClient.execute(httpGet);
} catch (IOException e) {
log.warn("An exception occurred while fetching the stream",e);
return null;
}
if (response.getStatusLine().getStatusCode() != 200) {
log.warn("Could not fetch stream. Status line: "+ response.getStatusLine());
return null;
}
int MetadataOffset = retrieveMetadataOffset(response);
if (MetadataOffset == 0) {
log.info("Could not find Metadata for url:"+ streamUrl);
return null;
}
List<Metadata> Metadata = extractMetadata(response,MetadataOffset);
if (Metadata == null || Metadata.isEmpty()) {
return null;
}
return extractSongInfo(Metadata);
}
private List<Metadata> extractMetadata(HttpResponse response,int MetadataOffset) {
String MetadataStr;
try(InputStream stream = response.getEntity().getContent()) {
if (stream.skip(MetadataOffset) != MetadataOffset) {
log.warn("Something went wrong while skipping to Metadata offset");
return null;
}
int MetaDataLength = stream.read() * 16;
MetadataStr = getMetadataStr(stream,MetaDataLength);
if (MetadataStr == null) {
return null;
}
} catch (IOException e) {
log.warn("Something went wrong while reading the stream",e);
return null;
} //Hangs here
//rest of the method
}
我注意到 response.getEntity().getContent()
返回的流是 EofSensorInputStream
类型,所以我想知道它是否正在等待一个永远不会到来的 EOF 字符。
代码正常运行且流正常关闭的流示例:https://icecast.omroep.nl/radio2-bb-mp3、http://live-mp3-128.kexp.org 代码无法正常工作的流示例,因为流永远不会关闭并永远挂起:https://kexp-mp3-128.streamguys1.com/kexp128.mp3
解决方法
出现这个问题是因为在内容流上调用 close()
会尝试消耗剩余的内容。这目前在 documentation 中没有明确提及(另见 HTTPCORE-656),但在 tutorials 中提及:
关闭内容流和关闭响应的区别在于,前者会尝试通过消耗实体内容来保持底层连接处于活动状态,而后者会立即关闭并丢弃连接。
[...]
然而,在某些情况下,只需要检索整个响应内容的一小部分,而消耗剩余内容和使连接可重用的性能损失太高,在这种情况下,可以通过关闭来终止内容流回应。
因此,在您的情况下,不关闭 InputStream
返回的 getContent()
而仅关闭 HttpResponse
(您显然还没有这样做)似乎是合适的).
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。