Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: HttpURLConnection doesn't disconnect

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();
        }
    }
like image 394
Daniele B Avatar asked Jul 06 '14 18:07

Daniele B


People also ask

How do I close HttpURLConnection?

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.

Do I need to disconnect HttpURLConnection?

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.

What is HttpURLConnection in Android?

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.

Which is the following used in HttpURLConnection?

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) .


1 Answers

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.

like image 155
Manish Mulimani Avatar answered Sep 27 '22 18:09

Manish Mulimani