安全使用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有关,但对许多先前版本和后期版本来说也可能是准确的。
从我可以告诉,代码归结为:
- 如果远程服务器发送带有可以parsing为正整数的“超时”值的“Keep-Alive”头文件,那么该超时使用秒数。
- 如果远程服务器发送“Keep-Alive”标题,但没有可以parsing为正整数的“超时”值, 并且 “usingProxy”为true,则超时值为60秒。
- 在其他情况下,超时时间是5秒。
这个逻辑分为两个地方:围绕sun.net.www.http.HttpClient的线725(在“parseHTTPHeader”方法中)和sun.net.www.http.KeepAliveCache的 120行(在“put”方法)。
所以,有两种方法来控制超时时间:
- 控制远程服务器并将其configuration为发送具有适当超时字段的Keep-Alive标题
- 修改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/ 。