当使用HttpURLConnection时,如果我们没有'得到'并使用它,那么InputStream是否需要关闭?
即。这样安全吗?
HttpURLConnection conn = (HttpURLConnection) uri.getURI().toURL().openConnection();
conn.connect();
// check for content type I don't care about
if (conn.getContentType.equals("image/gif") return;
// get stream and read from it
InputStream is = conn.getInputStream();
try {
// read from is
} finally {
is.close();
}
其次,在完全读取所有内容之前关闭InputStream 是否安全 ?
是否存在将底层套接字置于ESTABLISHED或甚至CLOSE_WAIT状态的风险?
答案 0 :(得分:33)
根据http://docs.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html 和OpenJDK源代码。
(当keepAlive == true)
如果客户端调用了HttpURLConnection.getInputSteam()。 close (),则稍后调用HttpURLConnection。 disconnect ()将不关闭插座。即Socket被重用(缓存)
如果客户端没有调用close(),则调用disconnect()将关闭InputSteam并关闭Socket。
因此,为了重用Socket,只需调用InputStream close ()。不要调用HttpURLConnection 断开连接()。
答案 1 :(得分:28)
关闭InputStream是否安全 在它的所有内容之前 阅读
在关闭输入流之前,需要读取输入流中的所有数据,以便缓存底层TCP连接。我已经读过它在最新的Java中不应该被要求,但它总是被要求读取连接重用的整个响应。
查看此帖子:keep-alive in java6
答案 2 :(得分:18)
以下是有关保持活动缓存的一些信息。所有这些信息都与Java 6有关,但对于许多先前版本和更高版本而言可能也是准确的。
据我所知,代码归结为:
这个逻辑分为两个地方:sun.net.www.http.HttpClient的第725行(在“parseHTTPHeader”方法中)和sun.net.www.http.KeepAliveCache的第120行(在“put”方法中)。
因此,有两种方法可以控制超时时间:
有人会认为可以在不重新编译内部JDK类的情况下更改明显的任意五秒默认值,但事实并非如此。 2005年提出bug要求此能力,但Sun拒绝提供。
答案 3 :(得分:7)
如果您确实要确保连接已关闭,请致电conn.disconnect()
。
您观察到的开放连接是因为HTTP 1.1连接保持活动功能(也称为HTTP Persistent Connections)。
如果服务器支持HTTP 1.1并且未在响应头中发送Connection: close
,则在关闭输入流时,Java不会立即关闭底层TCP连接。相反,它会保持打开并尝试将其重新用于下一个发送到同一服务器的HTTP请求。
如果您根本不想要这种行为,可以将系统属性http.keepAlive
设置为false:
System.setProperty("http.keepAlive","false");
答案 4 :(得分:4)
如果HTTP请求失败(除了200之外的任何内容),您还必须关闭错误流:
SetNumberOfWorkers
如果您不这样做,所有未返回200的请求(例如超时)将泄漏一个套接字。
答案 5 :(得分:1)
当使用HttpURLConnection时,如果我们没有'得到'并使用它,那么InputStream是否需要关闭?
是的,它总是需要关闭。
即。这样安全吗?
不是100%,您冒着获得NPE的风险。更安全的是:
InputStream is = null;
try {
is = conn.getInputStream()
// read from is
} finally {
if (is != null) {
is.close();
}
}
答案 6 :(得分:0)
从Java 7开始,推荐的方法是
try (InputStream is = conn.getInputStream()) {
// read from is
// ...
}
与所有其他实现Closable
的类一样。 close()
在try {...}
块的末尾被调用。
关闭输入流也意味着您已经完成阅读。否则,连接将一直挂起,直到终结器关闭流为止。
如果要发送数据,则同样适用于输出流。