安全使用HttpURLConnection

时间:2011-01-22 11:31:09

标签: java http url network-programming

当使用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状态的风险?

7 个答案:

答案 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有关,但对于许多先前版本和更高版本而言可能也是准确的。

据我所知,代码归结为:

  1. 如果远程服务器发送“Keep-Alive”标头,其“timeout”值可以解析为正整数,则该秒数用于超时。
  2. 如果远程服务器发送“Keep-Alive”标头,但它没有“timeout”值,可以解析为正整数“usingProxy”为true,那么超时是60秒。
  3. 在所有其他情况下,超时为5秒。
  4. 这个逻辑分为两个地方:sun.net.www.http.HttpClient的第725行(在“parseHTTPHeader”方法中)和sun.net.www.http.KeepAliveCache的第120行(在“put”方法中)。


    因此,有两种方法可以控制超时时间:

    1. 控制远程服务器并将其配置为发送具有正确超时字段的Keep-Alive标头
    2. 修改JDK源代码并构建自己的代码。
    3. 有人会认为可以在不重新编译内部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 {...}块的末尾被调用。

关闭输入流也意味着您已经完成阅读。否则,连接将一直挂起,直到终结器关闭流为止。

如果要发送数据,则同样适用于输出流。