安全使用HttpURLConnection

当使用HttpURLConnection时,InputStream需要closures,如果我们不'得到'并使用它?

即这是安全的吗?

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(); } 

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

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

在读取所有内容之前closuresInputStream是安全的

您需要先closuresinputstream中的所有数据,然后才能caching底层的TCP连接。 我已经读过,它不应该在最新的Java需要,但它总是强制读取整个响应连接重用。

检查这篇文章: 保持在java6中

根据http://docs.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html和OpenJDK源代码。;

(当keepAlive == true时)

如果客户端调用了HttpURLConnection.getInputSteam()。 close (),稍后调用HttpURLConnection。 disconnect () 不会closures套接字。 即套接字重用(caching)

如果客户端不调用close(),调用disconnect()将closuresInputSteam并closuresSocket。

所以为了重用Socket,只需调用InputStream close ()。 不要调用HttpURLConnection disconnect ()。

以下是有关保持活动caching的一些信息。 所有这些信息都与Java 6有关,但对许多先前版本和后期版本来说也可能是准确的。

从我可以告诉,代码归结为:

  1. 如果远程服务器发送带有可以parsing为正整数的“超时”值的“Keep-Alive”头文件,那么该超时使用秒数。
  2. 如果远程服务器发送“Keep-Alive”标题,但没有可以parsing为正整数的“超时”值, 并且 “usingProxy”为true,则超时值为60秒。
  3. 在其他情况下,超时时间是5秒。

这个逻辑分为两个地方:围绕sun.net.www.http.HttpClient的线725(在“parseHTTPHeader”方法中)和sun.net.www.http.KeepAliveCache的 120行(在“put”方法)。


所以,有两种方法来控制超时时间:

  1. 控制远程服务器并将其configuration为发送具有适当超时字段的Keep-Alive标题
  2. 修改JDK源代码并构build自己的。

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

如果你真的想确保连接是closures的,你应该调用conn.disconnect()

您观察到的打开连接是由于HTTP 1.1连接保持活动function(也称为HTTP持久连接 )。 如果服务器支持HTTP 1.1并且不发送Connection: close在响应头中closuresinputstream时,Java不会立即closures下层TCP连接。 而是保持打开状态,并尝试将其重用到下一个HTTP请求到同一台服务器。

如果你不想要这个行为,你可以设置系统属性http.keepAlive为false:

 System.setProperty("http.keepAlive","false"); 

当使用HttpURLConnection时,InputStream需要closures,如果我们不'得到'并使用它?

是的,它总是需要closures。

即这是安全的吗?

不是100%,你冒着得到一个NPE的风险。 更安全的是:

 InputStream is = null; try { is = conn.getInputStream() // read from is } finally { if (is != null) { is.close(); } } 

如果HTTP请求失败(除了200之外的任何内容),还必须closures错误stream:

 try { ... } catch (IOException e) { connection.getErrorStream().close(); } 

如果你不这样做,所有不返回200的请求(例如超时)将泄漏一个套接字。 有关更多详细信息,请参阅http://scotte.github.io/2015/01/httpurlconnection-socket-leak/