Home arrow static arrow Java Programming [Archive] - JSSE and NIO
Warning: Creating default object from empty value in /www/htdocs/w008deb8/wiki/components/com_staticxt/staticxt.php on line 51
Java Programming [Archive] - JSSE and NIO
10 Duke Stars available
This topic has 2 replies on 1 page.

Registered: 1/19/04
JSSE and NIO  
Jun 22, 2004 7:20 AM

I need to implement secure (https) non-blocking communication.
I want to use java.nio with JSSE.

I found a paper on that subject (http://www-106.ibm.com/developerworks/java/library/j-sslnb.html?ca=dgr-lnxw16JSSE-NIO) and tried to run the example program.

Unfortunately, when I run the program, the output contains many "bad characters".

When I comment this line : s.setSoTimeout(25); in nbChannel.java, the output is OK.

I think the SocketTimeoutException that is throw corrupts the socket and prevents it from decoding the
HTTPS response correctly???

But the problem is that the nbChannel becomes a blocking one if I remove
the timeout !!

I really need to use JSSE and NIO(non-blocking) in my application.
Does anyone have an idea ?
Is this a bug ?
Do you get the same results (bad characters) ?

Here is the code :
/* nbChannel.java - Source code to accompany the article * "The Easy Way to Non-blocked Sockets". * * Article copyright (C) 2003 by Kenneth Ballard. * First published by IBM developerWorks, 2003. * * Source code copyright (C) 2003 by Kenneth Ballard. * Use freely as you wish, acknowledgements not required. * Source code provided "as-is" without warranty of any kind. */ import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.net.SocketTimeoutException;import java.nio.ByteBuffer;import java.nio.channels.ByteChannel;import java.nio.channels.Channels;import java.nio.channels.ReadableByteChannel;import java.nio.channels.WritableByteChannel; class nbChannel implements ByteChannel{    Socket s;    InputStream is; OutputStream os;    ReadableByteChannel rbc;    WritableByteChannel wbc;     public nbChannel(Socket socket) throws IOException    {        s = socket;        is = s.getInputStream();        os = s.getOutputStream();        rbc = Channels.newChannel(is);        wbc = Channels.newChannel(os);    }     public int read(ByteBuffer dst) throws IOException    {        /* If there's no space available or if no data is available, return */         int y = checkConnection();        if(y <= 0) return y;         dst.put((byte)y);        return rbc.read(dst)+1;    }     /* Checks for a connection by attempting to read only one byte */     protected int checkConnection() throws IOException    {        /* Store the current timeout */         int y = s.getSoTimeout();        int p = -1;         /* Set a new timeout to a very short amount of time */         s.setSoTimeout(25);         /* Attempt to read, catching the exception if it fails. If the         * connection times out, though, the connection is still open,         * it just doesn't have anything to read.         */         try { p = is.read(); }        catch(SocketTimeoutException e) { p = 0; }        catch(IOException e) { p = -1; }         /* Reset the timeout */         if(p != -1) s.setSoTimeout(y);        return p;    }     public int write(ByteBuffer src) throws IOException    {        int x, y = s.getSendBufferSize(), z = 0;        int expectedWrite;        byte [] p = src.array();        ByteBuffer buf;                if(src.remaining() == 0) return 0;                /* Allocate a temporary buffer for writing the data to the channel */                buf = ByteBuffer.allocateDirect(y);        os.flush();         for(x = 0; x < p.length; x += y)        {            if(p.length - x < y)            {                buf.put(p, x, p.length - x);                expectedWrite = p.length - x;            }            else            {                buf.put(p, x, y);                expectedWrite = y;            }                        buf.flip();             z = wbc.write(buf);            os.flush();            if(z < expectedWrite) break;            buf.clear();        }                if(x > p.length) return p.length;        else return x + z;    }        public void close() { try { s.close(); } catch(Exception e) {} }     /* Thrown in to avoid the "should be declared abstract" messages.  Will     * always return false, though.     */     public boolean isOpen() { return s.isConnected(); }}

/* Implements a secure, non-blocking connection to Verisign and   downloads their home page */ import java.nio.ByteBuffer;import java.nio.channels.ReadableByteChannel;import java.nio.channels.WritableByteChannel; import javax.net.ssl.SSLSocket;import javax.net.ssl.SSLSocketFactory; public class HTTPSClient{    public static void main(String [] args) throws Exception    {        ByteBuffer buffer;        ReadableByteChannel is;        WritableByteChannel os;        nbChannel socketChannel;         String request; int k;         SSLSocketFactory sslFactory =            (SSLSocketFactory)SSLSocketFactory.getDefault();        SSLSocket sslSocket =            (SSLSocket)sslFactory.createSocket("www.verisign.com", 443);         sslSocket.startHandshake();         socketChannel = new nbChannel(sslSocket);         is = (ReadableByteChannel)socketChannel;        os = (WritableByteChannel)socketChannel;         request = "GET / HTTP/1.0\r\n";        request += "Host: www.verisign.com\r\n";        request += "Connection: close\r\n\r\n";               buffer = ByteBuffer.allocate(request.getBytes().length);        buffer.put(request.getBytes());        buffer.flip();         os.write(buffer);        buffer.clear();         k = is.read(buffer);        while(k >= 0)        {            buffer.flip();            System.out.write(buffer.array(), 0, k);            buffer.clear();            k = is.read(buffer);        }         sslSocket.close();    }}

Registered: 6/22/04
Re: JSSE and NIO  
Jun 22, 2004 9:00 AM (reply 1 of 2)

I've tried your code and I have the same problem, I don't know what wrong exactly but it's seems to me that the characters are still encoded.
The only explanation I found is that before throwing the SocketTimeoutException, JAVA returns the datas even if decoding is not over yet when there is data available in the Stream.

If any body has a solution please post it, I have the same problem...

Registered: 1/19/04
Re: JSSE and NIO  
Jun 23, 2004 5:22 AM (reply 2 of 2)

Does somebody has the same exception ?
I am pretty sure its a bug.
Is there someone who knows a workaround to write a non-blocking https client ?
This topic has 2 replies on 1 page.