Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpsUrlConnection and keep-alive

I am using com.sun.net.httpserver.HttpsServer in my current project which deals with client-authentification etc.. Currently it only prints out the clients address/port, so that I can check if one TCP-connection is used for multiple requests (keep-alive) or if a new connection is established for every request (and thus a new SSL-handshake is made every time). When I use FireFox to make multiple request against the server I can see that keep-alive is working. So the server part works fine with GET and POST-requests.

If I use HttpURLConnection to make a request against the Server (in this case using no SSL) keep-alive works, too: Only one connection is established for multiple sequentially started requests.

But if I use HttpsURLConnection (using exactly the same code, but using SSL) then keep-alive is not working anymore. So for each request a new connection is established, although I am using the same SSLContext (and SSLSocketFactory):

// URL myUrl = ... // SSLContext mySsl = ... HttpsURLConnection conn = (HttpsURLConnection) myUrl.openConnection(); conn.setUseCaches(false); conn.setSSLSocketFactory(mySsl.getSocketFactory());  conn.setRequestMethod("POST"); // send Data // receive Data 

How do I force HttpsURLConnection to use keep-alive because many requests will lead to many SSL-handshakes which is a real performance issue?

Update (2012-04-02): Instead of calling mySsl.getSocketFactory() each time, I tried to cache the SSLSocketFactory. But nothing changed. The problem still exists.

like image 271
Biggie Avatar asked Mar 30 '12 12:03

Biggie


People also ask

How do I keep my HTTP connection alive?

using HTTP/1.0, started to add an unofficial extension (to the protocol) named "keep-alive" in order to allow the reuse of a connection for multiple requests/responses. When the server receives this request and generates a response, if it supports keep-alive then it also adds the same above header to the response.

What is Keep-Alive in response header?

The Keep-Alive header is a general-type header. This header is used to hint at how the connection may be used to set a timeout and a maximum amount of requests. It can also be used to allow a single TCP connection to remain open for multiple HTTP requests/responses (default HTTP connection closed after each request).

What is the purpose of Keep-Alive in HTTP?

The HTTP keep-alive header maintains a connection between a client and your server, reducing the time needed to serve files. A persistent connection also reduces the number of TCP and SSL/TLS connection requests, leading to a drop in round trip time (RTT).

Should Enable Keep-Alive?

Enabling Keep-Alive ensures that a single TCP connection is used to transfer multiple files from the server to the browser. This helps your page load faster as the browser doesn't need to establish multiple connections to retrieve all your page resources.


2 Answers

I ran into this exact same problem and finally have a solution after some in-depth debugging.

Http(s)UrlConnection does handle Keep-Alive by default but sockets must be in a very specific condition in order to be reused.

These are:

  • Input streams must be fully consumed. You must call read on the input stream until it returns -1 and also close it.
  • Settings on the underlying socket must use the exact same objects.
  • You should call disconnect (yes this is counter-intuitive) on the Http(s)URLConnection when done with it.

In the above code, the problem is:

conn.setSSLSocketFactory(mySsl.getSocketFactory()); 

Saving the result of getSocketFactory() to a static variable during initialization and then passing that in to conn.setSSLSocketFactory should allow the socket to be reused.

like image 167
Bill Healey Avatar answered Sep 21 '22 11:09

Bill Healey


I couldn't get it working with HttpsUrlConnection. But Apache's HTTP client handles keep-alive with SSL connections very well.

like image 36
Biggie Avatar answered Sep 24 '22 11:09

Biggie