我正在使用apachehttpclient从无线流中获取元数据。我要做的是发出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 example 由于流永远不会关闭和挂起,因此代码无法正常工作的流:https://kexp-mp3-128.streamguys1.com/kexp128.mp3
1条答案
按热度按时间n3schb8v1#
发生此问题的原因是调用
close()
在内容流上,将尝试使用剩余的内容。目前文档中没有明确提到这一点(另请参见httpcore-656),但教程中提到了这一点:关闭内容流和关闭响应之间的区别在于,前者将尝试通过使用实体内容来保持底层连接的活动性,而后者则立即关闭并丢弃连接。
[...]
但是,在某些情况下,只需要检索整个响应内容的一小部分,而消耗剩余内容并使连接可重用的性能代价太高,在这种情况下,可以通过关闭响应来终止内容流。
因此,在您的情况下,似乎不关闭
InputStream
退回人getContent()
但只关闭HttpResponse
(显然你还没有做到)。