2

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)
PhilLab
  • 4,777
  • 1
  • 25
  • 77
  • FYI: Looking in the implementation of ``conn.getResponseCode()`` I also noticed a very interesting pitfall: it retrieves the inputStream itself but of course does not close it. So if you use this method, you have to retrieve the stream afterwards and close it yourself. – PhilLab Feb 08 '16 at 11:53

1 Answers1

2

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

Blackbelt
  • 156,034
  • 29
  • 297
  • 305
  • Unfortunately this does not change anything. I also tried using only ``conn.disconnect()`` and omitting ``is.close()`` as advised [here](http://stackoverflow.com/a/11533423) but the problem persists – PhilLab Feb 08 '16 at 12:05
  • did you write the server ? – Blackbelt Feb 08 '16 at 12:06
  • No, it is civetweb (fork of mongoose) – PhilLab Feb 08 '16 at 12:07
  • 1
    could you try adding `conn.setRequestProperty("Connection", "close");` after `openConnection` and see if it helps. – Blackbelt Feb 08 '16 at 12:09
  • thanks for pointing out one possible solution after another, awesome! I added them to the question to keep track of them because unfortunately they did not work – PhilLab Feb 08 '16 at 12:17
  • you are welcome. I am out of ideas. How are you debugging the load ? – Blackbelt Feb 08 '16 at 12:18
  • very naively - just by opening the windows task manager. I see a clear rise to 99% when initiating the requests and a drop back to <1% when I close the Android app again. – PhilLab Feb 08 '16 at 12:21