安全使用HttpURLConnection

Joe*_*oel 47 java url network-programming http

当使用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();
}
Run Code Online (Sandbox Code Playgroud)

其次,在完全读取所有内容之前关闭InputStream是否安全?

是否存在将底层套接字置于ESTABLISHED或甚至CLOSE_WAIT状态的风险?

And*_*Mao 34

根据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 disconnect().


Cra*_*lus 29

在读取所有内容之前关闭InputStream是否安全

在关闭输入流之前,需要读取输入流中的所有数据,以便缓存底层TCP连接.我已经读过它在最新的Java中不应该被要求,但它总是被要求读取连接重用的整个响应.

查看这篇文章:在java6中保持活着

  • @Joel:通过调用`HttpUrlConnection.disconnect()`,底层的tcp套接字被关闭.通过关闭输入流,底层的TCP套接字汇集购买reuse.The唯一需要注意的是,整个响应(或整个错误响应)应该从输入流中的顺序来读取要被高速缓存的TCP连接.无论您实际需要流中的整个数据,都始终建议这样做.检查我的答案中的帖子 (4认同)
  • 好文章,谢谢。有几件事我仍然不清楚。1)缓存的连接在丢弃之前会保留多长时间?我看不到“ 60秒钟不活动后放弃”类型的设置。2)我不清楚在调用close之后但在读取所有内容之前不知道连接将处于哪种状态-它表示将无法重新使用/缓存,这很好-但是底层插座实际上被关闭了吗? (2认同)

Sam*_*ard 18

以下是有关保持活动缓存的一些信息.所有这些信息都与Java 6有关,但对于许多先前版本和更高版本而言可能也是准确的.

据我所知,代码归结为:

  1. 如果远程服务器发送"Keep-Alive"标头,其"timeout"值可以解析为正整数,则该秒数用于超时.
  2. 如果远程服务器发送"保持活动"标头但它没有可以解析为正整数并且 "usingProxy"为真的"超时"值,则超时为60秒.
  3. 在所有其他情况下,超时为5秒.

这个逻辑分为两个地方:sun.net.www.http.HttpClient的第725行(在"parseHTTPHeader"方法中),以及sun.net.www.http.KeepAliveCache的第120行(在"put"中)方法).


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

  1. 控制远程服务器并将其配置为使用正确的超时字段发送Keep-Alive标头
  2. 修改JDK源代码并构建自己的代码.

有人会认为可以在不重新编译内部JDK类的情况下更改明显的任意五秒默认值,但事实并非如此.2005年提出了一个错误请求此功能,但Sun拒绝提供此错误.

  • 关于文献记录不佳的很好的研究.谢谢你的分享. (3认同)

Rob*_*ert 7

如果你真的想确保连接关闭,你应该打电话conn.disconnect().

您观察到的开放连接是因为HTTP 1.1连接保持活动功能(也称为HTTP持久连接).如果服务器支持HTTP 1.1并且未Connection: close在响应头中发送,则在关闭输入流时,Java不会立即关闭底层TCP连接.相反,它保持打开并尝试将其重用于下一个对同一服务器的HTTP请求.

如果您根本不想要此行为,则可以将system属性设置http.keepAlive为false:

System.setProperty("http.keepAlive","false");
Run Code Online (Sandbox Code Playgroud)