Search code examples
javasocketsbufferedreaderready

BufferedReader never ready (Socket programming in Java)


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.


Solution

  • There are 3 things that come to my mind:

    • You are re-opening the input stream in every receive call, and wrapping it into a BufferedReader. This might read more than a single line into the buffer, and after finishing (closing it), the remaining buffered bytes will no longer be available for subsequent receive calls
    • Did you think about using an own thread for reading the server messages? There it won't harm if it is blocked
    • I have experienced some problems when closing one side of a socket after writing data, and immediately closing it. Sometimes not all of the data was received by the other side, despite flush() and close() calls. Maybe this is also an issue in your situation

    Edit:
    Smiply keeping the in reference outside of the receive method will not fully solve your problem. You should use a while loop for reading all buffered messages and call the listener for everyone, e.g.:

    if (in.ready()) {
        String message;
        while ((message = in.readLine()) != null) {
            // ...
        }
     }
    

    But watch out as the last line might be a partially read message (e.g. 3 and 1/2 messages were buffered). If this is an issue, you could read the messages char-by-char for determining when a line ends, and use a PushbackReader for putting back incomplete messages.