public byte[] getUrlBytes(String urlSpec) throws IOException {
URL url = new URL(urlSpec);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = connection.getInputStream();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException(connection.getResponseMessage() + ": with " + urlSpec);
}
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = in.read(buffer)) > 0)
{
out.write(buffer, 0, bytesRead);
}
out.close();
return out.toByteArray();
} finally {
connection.disconnect();
}
}
I have several questions.
-
out.close()
This code calls out.close() and dosen’t call in.close().
Is it OK??
Or does connection.disconnect() perform in.close() internally? -
connection.disconnect()
I’m confused about the behavior of disconnect().https://docs.oracle.com/javase/9/docs/api/java/net/HttpURLConnection.html
Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.
—> java doc says that calling disconnect() may close TCP connection.https://developer.android.com/reference/java/net/HttpURLConnection.html
Disconnect. Once the response body has been read, the HttpURLConnection should be closed by calling disconnect(). Disconnecting releases the resources held by a connection so they may be closed or reused.
—> android doc recommends to always call disconnect().To reduce latency, this class may reuse the same underlying Socket for multiple request/response pairs. As a result, HTTP connections may be held open longer than necessary. Calls to disconnect() may return the socket to a pool of connected sockets.
—> android doc says that the connection keeps alive and the socket can be reused after disconnect(), right?void disconnect ()
Indicates that other requests to the server are unlikely in the near future. Calling disconnect() should not imply that this HttpURLConnection instance can be reused for other requests.
—> android doc says that the connection can’t be reused after disconnect(), right??==> In android, does disconnect() close TCP connection?
Does android recommend to disable persistent connection? -
handling IOException of getInputStream()
Java Training recommends to use getErrorStream() to reuse TCP connection.
In android, calling getErrorStream() is unnecessary??http://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html
When the application finishes reading the response body or when the application calls close() on the InputStream returned by URLConnection.getInputStream(), the JDK’s HTTP protocol handler will try to clean up the connection and if successful, put the connection into a connection cache for reuse by future HTTP requests.Do not abandon a connection by ignoring the response body. Doing so may results in idle TCP connections. That needs to be garbage collected when they are no longer referenced.
If getInputStream() successfully returns, read the entire response body.
When calling getInputStream() from HttpURLConnection, if an IOException occurs, catch the exception and call getErrorStream() to get the response body (if there is any).
Reading the response body cleans up the connection even if you are not interested in the response content itself. But if the response body is long and you are not interested in the rest of it after seeing the beginning, you can close the InputStream. But you need to be aware that more data could be on its way. Thus the connection may not be cleared for reuse.
Here’s a code example that complies to the above recommendation:
try {
URL a = new URL(args[0]);
URLConnection urlc = a.openConnection();
is = conn.getInputStream();
int ret = 0;
while ((ret = is.read(buf)) > 0) {
processBuf(buf);
}
// close the inputstream
is.close();
} catch (IOException e) {
try {
respCode = ((HttpURLConnection)conn).getResponseCode();
es = ((HttpURLConnection)conn).getErrorStream();
int ret = 0;
// read the response body
while ((ret = es.read(buf)) > 0) {
processBuf(buf);
}
// close the errorstream
es.close();
} catch(IOException ex) {
// deal with the exception
}
}