android httpurlconnection 异常,android – 抛出IOException时我们是否需要使用HttpURLConnection的错误流...

如果您不想向用户显示错误消息,请关闭InputStream或在finally块中调用HttpURLConnection上的disconnect,而不读取错误消息.这是您在大多数示例中看到的内容.

在浏览HttpURLConnection的实现时,我在其中一个source code中发现了以下评论.这可能是在不读取所有数据的情况下关闭连接的原因.

This should be invoked when the connection is closed unexpectedly to

invalidate the cache entry and to prevent the HTTP connection from

being reused. HTTP messages are sent in serial so whenever a message

cannot be read to completion,subsequent messages cannot be read

either and the connection must be discarded.

根据Android的HttpURLConnection实现,如遇异常:

>如果未读取错误且InputStream已关闭,则连接将被视为不可重复使用并关闭.

>如果您读取错误然后关闭InputStream,则连接被视为可重用,并被添加到连接池.

您可以在下图中看到可变连接&只要读取所有数据,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方法实现.在HttpURLConnection实例上调用disconnect将导致调用此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将添加到连接池中.这是FixedLengthInputStream的read方法实现:

@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,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,read);

if (bytesRemaining == 0) {

endOfInput(true);

}

return read;

}

当bytesRemaining变量变为0时,调用endOfInput,这将使用true参数进一步调用release方法,这将确保连接被合并.

protected final void endOfInput(boolean reuseSocket) throws IOException {

if (cacheRequest != null) {

cacheBody.close();

}

httpEngine.release(reuseSocket);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值