PhilLab
PhilLab

Reputation: 5007

How to close a persistent HTTP Connection without reading

I have an URLConnection which I want to cancel depending on the response code without reading any data. I closely followed the android training to build the following minimal example which floods the server with requests since no connection is ever released back to the handle pool for reuse

private String downloadUrl(String myurl) throws IOException {
    InputStream is = null;
    try {
        URL url = new URL(myurl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(10000 /* milliseconds */);
        conn.setConnectTimeout(15000 /* milliseconds */);
        conn.setRequestMethod("GET");
        conn.setDoInput(true);
        // Starts the query
        conn.connect();
        int response = conn.getResponseCode();
        Log.d(TAG, "The response code is: " + response);
        is = conn.getInputStream();

        // Do not read anything //String contentAsString = readIt(is, len);
        String contentAsString = "notReadingAnything";
        return contentAsString;
    } finally {
        if (is != null) {
            is.close();
        }
    }
}

private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {
        try {
            String result = new String();
            for (int i=0; i<100; i++) {
                result += downloadUrl(urls[0]);
            }
            return result;
        } catch (IOException e) {
            return "Unable to retrieve web page. URL may be invalid.";
        }
    }
    @Override
    protected void onPostExecute(String result) {
        Log.d(TAG, "The response is: " + result);
    }
}

Despite the docs explicitly stating

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

the server quickly reaches its maximum number of connections (50) and goes to 99% workload if I don't read the stream but works fine if I do read it. What is my mistake?

EDIT: Failed solution attempts so far (thanks to @Blackbelt for most of them)

  1. calling conn.disconnect() in the finally block
  2. calling conn.disconnect() instead of is.close() in the finally block
  3. Setting System.setProperty("http.keepAlive", "false"); before the first call
  4. Setting conn.setRequestProperty("Connection", "Close"); before connecting
  5. Setting "{enable_keep_alive", "no"} on the used backend server (Civetweb)

Upvotes: 2

Views: 2066

Answers (1)

Blackbelt
Blackbelt

Reputation: 157447

you should call disconnect() too. Accordingly to the documentation

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.

InputStream is = null;
HttpURLConnection conn = null;
try {
    URL url = new URL(myurl);
    conn = (HttpURLConnection) url.openConnection();

} finally {
    if (is != null) {
        is.close();
    } 
    if (conn != null) {
        conn.disconnect();
    } 
}

if you still are experiencing issues, is also possible that the bug is backend side

Upvotes: 2

Related Questions