by running netstat
on the server:
UNTIL A FEW DAYS AGO: I could see the connection being ESTABLISHED
only for about a second, and then it would disappear from the list
NOW: it stays as ESTABLISHED
for about 10 seconds, then it goes into FIN_WAIT1
and FIN_WAIT2
the Android code is the same, the server is still the same
is it possible that some kind of Android update might have changed things?
I can't really explain it.
I report the code below. The urlConnection.disconnect()
gets executed, but the connection remains established on the server.
HttpURLConnection urlConnection = null;
System.setProperty("http.keepAlive", "false");
try {
URL url = new URL(stringUrl);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream instream = new BufferedInputStream(urlConnection.getInputStream());
...
instream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection!=null) {
urlConnection.disconnect();
}
}
At the most you may close the stream derived from the URLConnection. In the HTTP request-response stateless protocol, the server will automatically close the socket after sending its response, and the client will automatically close its socket after receiving the response. There is nothing more to it I think.
Yes you need to close the inputstream first and close httpconnection next. As per javadoc. Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances.
HttpsURLConnection. HttpsURLConnection. HttpsURLConnection extends HttpURLConnection with support for https-specific features. The abstract class URLConnection is the superclass of all classes that represent a communications link between the application and a URL.
HttpURLConnection uses the GET method by default. It will use POST if setDoOutput(true) has been called. Other HTTP methods ( OPTIONS , HEAD , PUT , DELETE and TRACE ) can be used with setRequestMethod(String) .
The moment all data on input stream is consumed, the connection is released automatically and added to the connection pool. The underlying socket connection is not released, assuming the connection will be reused in near future. It is a good practice to call disconnect
in finally
block, as it takes care of connection release in case of exceptions
.
Here is the implementation of read method of FixedLengthInputStream:
@Override public int read(byte[] buffer, int offset, int count) throws IOException {
Arrays.checkOffsetAndCount(buffer.length, offset, count);
checkNotClosed();
if (bytesRemaining == 0) {
return -1;
}
int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
if (read == -1) {
unexpectedEndOfInput(); // the server didn't supply the promised content length
throw new IOException("unexpected end of stream");
}
bytesRemaining -= read;
cacheWrite(buffer, offset, read);
if (bytesRemaining == 0) {
endOfInput(true);
}
return read;
}
When bytesRemaining variable becomes 0, endOfInput is called which will futher call release method with true parameter, which will ensures the connection is pooled.
protected final void endOfInput(boolean reuseSocket) throws IOException {
if (cacheRequest != null) {
cacheBody.close();
}
httpEngine.release(reuseSocket);
}
Here is the release method implementation. The last if check ensures whether connection need to be closed down or added to the connection pool for reuse.
public final void release(boolean reusable) {
// If the response body comes from the cache, close it.
if (responseBodyIn == cachedResponseBody) {
IoUtils.closeQuietly(responseBodyIn);
}
if (!connectionReleased && connection != null) {
connectionReleased = true;
// We cannot reuse sockets that have incomplete output.
if (requestBodyOut != null && !requestBodyOut.closed) {
reusable = false;
}
// If the headers specify that the connection shouldn't be reused, don't reuse it.
if (hasConnectionCloseHeader()) {
reusable = false;
}
if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
reusable = false;
}
if (reusable && responseBodyIn != null) {
// We must discard the response body before the connection can be reused.
try {
Streams.skipAll(responseBodyIn);
} catch (IOException e) {
reusable = false;
}
}
if (!reusable) {
connection.closeSocketAndStreams();
connection = null;
} else if (automaticallyReleaseConnectionToPool) {
HttpConnectionPool.INSTANCE.recycle(connection);
connection = null;
}
}
}
Note: I had previously answered couple of SO questions related to HttpURLConnection, which can help you in understanding the underlying implementation. Here are the links : Link1 and Link2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With