SSLSocket BufferedReader blocking problem

I have a client program which connects to an Apache server, sends some HTTP messages and retrieves the responses.

An example message is:

OPTIONS / HTTP/1.1

Host: 127.0.0.1

Accept: */*

The response from Apache is:

HTTP/1.1 200 OK

Date: Wed, 07 Mar 2007 14:57:16 GMT

Server: Apache/2.2.3 (Unix) mod_ssl/2.2.3 OpenSSL/0.9.8a DAV/2

DAV: 1,2

DAV: <http://apache.org/dav/propset/fs/1>

MS-Author-Via: DAV

Allow: OPTIONS,GET,HEAD,POST,DELETE,TRACE,PROPFIND,PROPPATCH,COPY,MOVE,LOCK,UNLOCK

Content-Length: 0

Content-Type: httpd/unix-directory

This is the code that gets the response from Apache, thein variable is a BufferedReader connected to the InputStream of the SSLSocket.

private String getResponse()throws IOException{

String response ="";

int c = in.read();

char ch;

long start = System.currentTimeMillis();

while (in.ready() && c != -1){

ch = (char) c;

response += ch;

c = in.read();

}

long finish = System.currentTimeMillis();

System.out.println(finish - start);

ch = (char) c;

response += ch;

return response;

}

The output to the console is how long it took to get the whole message from the InputStream. In HTTP (Socket) mode this number is between 0-20 milliseconds but when i use HTTPS (SSLSocket) mode it is approx 5000! This number is independent of the time it takes to handshake with the server.

In SSL mode the above method fails actually, becausein.ready() returns false the first time, instead i have to modify it to:

while ((c = in.read()) != -1){

ch = (char) c;

response += ch;

System.out.print(ch);

}

In which case, i get the whole message printed to the console as fast as HTTP mode but on the final evaluation ofin.read() it takes the previously stated 5000 ms to finally exit the loop and return the Stringresponse.

I am certain my Apache server is configured correctly as if i use a web browser to navigate the site in HTTPS the response is instant as like in unsecure HTTP mode.

So why am i seeing this 5000 ms delay, when i reach the end of the stream in the BufferedReader?

There should be no difference in reading the BufferedReader when using either HTTP or HTTPS mode, given that i've accounted for the time it takes to handshake, right?

[3119 byte] By [sean_antonya] at [2007-11-26 20:40:41]
# 1

Wrong. SSL does encryption and decryption. The time required by this is non-zero.

ready() always returns false on a reader derived from an SSLSocket. Your code is better off without it in any case.

I would use a BufferedReader or BufferedInputStream between the reading code and the SSLSocket.

ejpa at 2007-7-10 1:59:06 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 2
Thanks for your reply, I am already using a BufferedReader like so:in = new BufferedReader(new InputStreamReader(socket.getInputStream()));How would you recommend i get rid of this 5000 ms delay?
sean_antonya at 2007-7-10 1:59:06 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 3

The final evaluation of in.read() happens at EOF which requires an SSL close_notify message to be exchanged in both directions, which takes a finite non-zero time.

5 seconds does seem excessive though. Are you using HttpsURLConnection, or an SSLSocket directly? If you're using HttpsURLConnection (or an https: URL) you could read until you've got the entire content-length instead of reading to EOF, or you could try setting the Connection header to 'close' before you get any streams from the URLConnection. I'm thinking that maybe the web server is keeping the connection alive for 5 seconds and you're just blocked in the read waiting for that.

ejpa at 2007-7-10 1:59:06 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 4
I'm using an SSLSocket directly, however i will see if i can modify my code to use a HttpsURLConnection and try out your recommendations.I'll post back when i've got some results, thanks!
sean_antonya at 2007-7-10 1:59:06 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 5
I remembered why i wasn't using HttpsURLConnection, so moved on to your next recommendation of adding the "Connection: close" header to my HTTP request messages, which worked!I am really happy that's working now, thanks a lot!
sean_antonya at 2007-7-10 1:59:06 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 6

hi,

I have the same problem. I am using httpsConnection

I set

httpsConn.setRequestProperty("Connection", "close");

and then,

HttpsURLConnection httpsConn = (HttpsURLConnection) conn;

:

:

InputStreamReader isr = new InputStreamReader(httpsConn.getInputStream());

Creating connection This one takes apporoxmately 3-4 seconds.

And reading input stream takes about 3-4 seconds

for one transaction, it takes about 6-7 seconds which is not accceptable. Please help!

msasikumara at 2007-7-10 1:59:06 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 7
Every transaction, or only the first? There is an SSL handshake to perform the first time which takes appreciable CPU time at both ends, and the exchange of seven to ten messages.
ejpa at 2007-7-10 1:59:06 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 8

Thanks Ejp.

I need to contact the server only once per call from a outside program.

1. open connection

2. post SOAP

3. Read reply

4. write the reply to a file

the whole thing takes about 6-7 seconds.

I can see some significant improvement with SSLSocket, over https.

I will try to make it work with SSLSocket.

msasikumara at 2007-7-10 1:59:06 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...