Search code examples
androidhttphttpurlconnectionkeep-alive

android httpurlconnection slow on data connection


Why is the first http request on data so slow?

I'm using something on the following lines: Doing 3 HTTP requests in a row (one after each other) and then wait a given time and loop again with doing the 3 HTTP requests.

I'm using keep-alive which is basically also working but on the first HTTP request there is a 2 second penalty each time I start with the 3 HTTP request. Only the first HTTP request has this 2 second penalty. If I lower the time waiting between the consecutive HTTP requests to something like 200ms all of the request are fast without having the first one seeing this 2 second penalty.

Obviously this sounds like the first request might not use the keep alive connection but that is actually not the case. I run tcpdump on the server and I can clearly see that all requests are using the same TCP connection without closing and building up again a new connection. The keep alive setting on the server is set to 60s while the time waiting on the app is for example 5 seconds. Also when I switch to WIFI this behavior I cannot see. With the same time waiting all requests are fast.

The http connect code is using HttpURLConnection and looks like the following:

m_res.error = null;
HttpURLConnection connection;
try {
    connection = (HttpURLConnection)(new URL(m_url + "/" + m_call.command).openConnection());
    connection.setDoOutput(true); // triggers POST.
    connection.setDoInput(true);
    connection.setRequestProperty("Accept-Charset", m_charset);
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + m_charset);
    connection.setRequestProperty("Connection", "Keep-Alive");
    connection.setRequestProperty("Accept-Encoding", "gzip");
    //connection.setChunkedStreamingMode(0);
    OutputStream output = null;

    try {
        output = connection.getOutputStream();
        output.write(m_call.query_string.getBytes(m_charset));
        InputStream response = null;
        try {
            response = connection.getInputStream();
            if ("gzip".equals(connection.getContentEncoding())) {
                response = new GZIPInputStream(response);
            }
        }
        catch (IOException e) {
            response = connection.getErrorStream();
        }
        if (response == null) {
            m_res.error = "Connection Error";
        }
        else {
            m_res.body = getAsString(response);
            m_res.status = connection.getResponseCode();
        }
    } 
    catch (IOException e) {
        e.printStackTrace();
        m_res.error = "Connection Error";
    }
    finally {
        if (output != null) 
                try { 
                    output.close(); 
                } catch (IOException logOrIgnore) {}
        }
    }
}

Solution

  • I think one possible answer to this is that the devices data connection on a layer below IP is changing its status e.g. maybe there is some sort of standby status which kicks in when there is no incoming or outgoing data for a given time e.g. like in my example 5 seconds.