BufferedReader never ready (Socket programming in Java)

Sadface picture Sadface · May 19, 2011 · Viewed 9.4k times · Source

I have socket already declared socket like this:

serverAddr = InetAddress.getByName(this.ip);
socket = new Socket(serverAddr, port);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

however, the following doesn't work. in.ready() always returns false and if removed the program will freeze at String message = in.readLine();

private void receive() {
        try {
            InputStreamReader isr = new InputStreamReader(socket.getInputStream());
            System.out.println(isr.getEncoding());
            BufferedReader in = new BufferedReader(isr);
            if (in.ready()) {
                String message = in.readLine();
                if (message != null) {
                    if (listener != null) {
                        listener.receiveMessage(ip, message);
                    } else {
                        print("Client recieved: " + message);//
                    }
                }
            }
            in.close();
        } catch (Exception e) {
            print("Error with input stream: " + e);
            disconnect();
        }

    }

How could i solve this?

EDIT:

This is how sending looks like in my server class: out.println(message); out.flush(); This happens in a loop whenever i've put something in message. out is closed after this loop.

Answer

Stephen C picture Stephen C · May 19, 2011

You shouldn't be using ready() like this. The javadoc says this:

"Returns: True if the next read() is guaranteed not to block for input, false otherwise. Note that returning false does not guarantee that the next read will block. "

Your code is implicitly assuming that ready() -> false means that the next read will block. In actual fact, it means the next read might or might not block.

As @EJP says ... just do the read call.


What could i do to prevent a block though? The client will be unable to send anything if it's blocked

If blocking in read is a problem for your application, either use a separate thread to do the reading, or change your code to use NIO channel selectors.