根据Oracle Java的技术指南,我们应该在HttpURLConnection
抛出时消耗IOException
的错误流
http://docs.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html
你可以做些什么来帮助Keep-Alive?不要放弃连接 通过忽略响应主体。这样做可能会导致TCP空闲 连接。当它们不是时,需要进行垃圾收集 更长的参考。
如果getInputStream()成功返回,请读取整个响应 体。
从HttpURLConnection调用getInputStream()时,如果是 发生IOException,捕获异常并调用getErrorStream() 得到响应主体(如果有的话)。
即使您没有,阅读响应正文也会清除连接 对响应内容本身感兴趣。但如果反应机构是 看到之后,你对其余部分并不感兴趣 一开始,你可以关闭InputStream。但你需要注意 更多的数据可能会在路上。因此连接可能不是 清除再利用。
这是符合上述建议的代码示例:
这是代码示例
try {
URL a = new URL(args[0]);
URLConnection urlc = a.openConnection();
is = conn.getInputStream();
int ret = 0;
while ((ret = is.read(buf)) > 0) {
processBuf(buf);
}
// close the inputstream
is.close();
} catch (IOException e) {
try {
respCode = ((HttpURLConnection)conn).getResponseCode();
es = ((HttpURLConnection)conn).getErrorStream();
int ret = 0;
// read the response body
while ((ret = es.read(buf)) > 0) {
processBuf(buf);
}
// close the errorstream
es.close();
} catch(IOException ex) {
// deal with the exception
}
}
这适用于Android平台吗?因为我在大多数Android代码示例中都没有看到这样的技术。
答案 0 :(得分:6)
如果您不想向用户显示错误消息,请关闭InputStream
或在disconnect
块中的HttpURLConnection
上调用finally
,而不会阅读错误消息。这是你在大多数例子中看到的。
在浏览HttpURLConnection的实现时,我在其中一个source code中发现了以下评论。这可能就是为什么在没有读取所有数据的情况下关闭连接的原因。
当连接意外关闭时应调用此方法 使缓存条目无效并阻止HTTP连接 被重用。无论何时消息,HTTP消息都是串行发送的 无法读取完成,后续消息无法读取 或者必须丢弃连接。
根据Android的HttpURLConnection
实现,如果发生异常:
InputStream
已关闭,则连接将被视为不可重复使用并关闭。 InputStream
,则连接被视为可重复使用,并被添加到连接池中。您可以在下图中看到变量connection
&读取所有数据后,connectionReleased
分别设置为null
和true
。请注意,getErrorStream
会返回InputStream
,因此它在异常情况下也有效。
代码分析:让我们看一下FixedLengthInputStream专门的InputStream
实现。以下是close
方法实现:
@Override public void close() throws IOException {
if (closed) {
return;
}
closed = true;
if (bytesRemaining != 0) {
unexpectedEndOfInput();
}
}
实例变量bytesRemaining
包含要读取的InputStream
上仍可用的字节数。以下是unexpectedEndOfInput方法实现:
protected final void unexpectedEndOfInput() {
if (cacheRequest != null) {
cacheRequest.abort();
}
httpEngine.release(false);
}
这是release方法实现。在disconnect
实例上调用HttpURLConnection
会导致调用此release
方法,并将false
作为参数。
最后一次if
检查可确保是否需要关闭连接或将其添加到连接池以供重复使用。
public final void release(boolean reusable) {
// If the response body comes from the cache, close it.
if (responseBodyIn == cachedResponseBody) {
IoUtils.closeQuietly(responseBodyIn);
}
if (!connectionReleased && connection != null) {
connectionReleased = true;
// We cannot reuse sockets that have incomplete output.
if (requestBodyOut != null && !requestBodyOut.closed) {
reusable = false;
}
// If the headers specify that the connection shouldn't be reused, don't reuse it.
if (hasConnectionCloseHeader()) {
reusable = false;
}
if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
reusable = false;
}
if (reusable && responseBodyIn != null) {
// We must discard the response body before the connection can be reused.
try {
Streams.skipAll(responseBodyIn);
} catch (IOException e) {
reusable = false;
}
}
if (!reusable) {
connection.closeSocketAndStreams();
connection = null;
} else if (automaticallyReleaseConnectionToPool) {
HttpConnectionPool.INSTANCE.recycle(connection);
connection = null;
}
}
}
您共享的代码,在其中处理IOException,读取错误流然后关闭,确保Connection可重用并添加到连接池。从InputStream
读取所有数据的那一刻,Connection
被添加到连接池。以下是read
的{{1}}方法实现:
FixedLengthInputStream
当@Override public int read(byte[] buffer, int offset, int count) throws IOException {
Arrays.checkOffsetAndCount(buffer.length, offset, count);
checkNotClosed();
if (bytesRemaining == 0) {
return -1;
}
int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
if (read == -1) {
unexpectedEndOfInput(); // the server didn't supply the promised content length
throw new IOException("unexpected end of stream");
}
bytesRemaining -= read;
cacheWrite(buffer, offset, read);
if (bytesRemaining == 0) {
endOfInput(true);
}
return read;
}
变量变为0时,将调用endOfInput,这将使用bytesRemaining
参数进一步调用release
方法,这将确保合并连接。
true
答案 1 :(得分:0)
如果它是针对Java记录的,那么它就是对Android平台的绑定。