views:

122

answers:

2

I have a server running that accepts connections made through client sockets, I need to read the input from this client socket, now suppose the client opened a connection to my server without sending anything through the server's socket outputstream, in this case, while my server tried to read the input through the client socket's inputstream, an exception will be thrown, but before the exception is thrown i would like a timeout say of 5 sec, how can I do this? currently here's how my code looks like on the server side:

try 
    {
        InputStreamReader clientInputStream = new InputStreamReader(clientSocket.getInputStream());
        int c;
        StringBuffer requestBuffer = new StringBuffer();
        while ((c = clientInputStream.read()) != -1) 
        { 
            requestBuffer.append((char) c);
            if (requestBuffer.toString().endsWith(("\r\n\r\n")))
                break;
        }
        request = new Request(requestBuffer.toString(), clientSocket);
    } 
    catch (Exception e) // catch any possible exception in order to keep the thread running
    {
        try 
        {
            if (clientSocket != null)
                clientSocket.close();
        } catch (IOException ex) 
        {
            ex.printStackTrace();
        }
        System.err.println(e);
        //e.printStackTrace();
    }
A: 

Have you tried setting the timeouts on the underlying socket ? See Socket.setSoTimeout(). From the doc:

With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid

Brian Agnew
no but I tried doing this now:clientSocket.setSoTimeout(5000);but an exception is still thrown immediately.
Noona
what's the exception class and message?
mdma
java.net.SocketException: Connection resetand its source is this line: while ((c = clientInputStream.read()) != -1)
Noona
Perhaps this will help. http://stackoverflow.com/questions/62929/java-net-socketexception-connection-reset
mdma
+2  A: 

The textbook answer is to set soTimeout on your socket, which you can do. However, that does not work in all cases. A friend of mine once demonstrated this by pulling out my network cable. I'd set soTimeout with a value of 30 seconds, yet my app just hung there, forever.

To get dependable timeouts, it is best to separate your I/O onto anther thread. If the thread doesn't come back with a response within the given time, you can try interrupting it, closing the streams and ultimately destroying the thread. This won't get you any further but, will try to clean up the streams. Once timeout has occurred, you will need to consider the current communication lost, restablish a connection and resend the previous command to repeat the communication. A command-pattern can help here. It's much easier to do if the commands are idempotent and can be executed multiple times. Being able to repeat failed requests can be used to deal with intermittent I/O errors.

mdma
currently I have this code running in a separate thread.
Noona
great, then setSoTimeout, which works most of the time, but also be prepared to interrupt your thread if it does not come back within time. Note that in some cases not even interrupt will get your thread out of waiting for I/O (I know it should, but in practice it doesn't) so if interrupt does not give you back control, be prepared to just close the streams, ditch the thread and start over with a new connection.
mdma
I want to keep the thread running since it's contained in a threadpool that I prepared and started upon starting the server. and in my comment to Brian I said that the exception was still thrown immediately.
Noona