How to automatically update server and client side in java

1.5k Views Asked by At

I'm learning distributed systems basics and currently I'm trying to do a simple yet realistic messenger between one server and one client. What I do intend is that on each endpoint socket side (Server and Client) text automatically updates (like a real "messaging app"). In other words, I want that the moment I write and "send" the message, it automatically appears on recipient side. What I have now follows this schema:

  1. I send a message (let's assume from client)
  2. To see that message on Server's side I need to reply first (because Server's BufferedReader / Client's PrintWriter is only read after asking for the answer)

My code:

public class ClientSide {
    public static void main(String [] args){
        String host_name = args[0];
        int port_number = Integer.parseInt(args[1]);

        try {
            Socket s = new Socket(host_name, port_number);

            PrintWriter out =
                    new PrintWriter(s.getOutputStream(), true);

            BufferedReader in = 
                    new BufferedReader(
                        new InputStreamReader(s.getInputStream()));

            BufferedReader stdIn = 
                    new BufferedReader(
                        new InputStreamReader(System.in));


            String answer;

            while ((answer = stdIn.readLine()) != null) {
                out.println(answer);
                System.out.println("\nlocalhost said\n\t" + in.readLine());
            }

        } catch (IOException ex) {
            Logger.getLogger(ClientSide.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}


public class ServerSide {
    public static void main(String [] args){
        int port_number = Integer.parseInt(args[0]);

        try {
            ServerSocket ss = new ServerSocket(port_number);
            Socket tcp = ss.accept();

            PrintWriter out = 
                    new PrintWriter(tcp.getOutputStream(), true);

            BufferedReader in =
                    new BufferedReader(
                        new InputStreamReader(tcp.getInputStream()));

            BufferedReader stdIn = 
                    new BufferedReader(
                        new InputStreamReader(System.in));

            String answer;
            while ((answer = stdIn.readLine()) != null){
                out.println(answer);
                System.out.println("\nClient said\n\t" + in.readLine());
            }

        } catch (IOException ex) {
            Logger.getLogger(ServerSide.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

How can I do this? Does it involve advanced knowledge on the matter? Thanks in advance.

1

There are 1 best solutions below

0
On

The core problem is that you want to wait for two events concurrently -- either a message from the socket, or input from the user!

You want to wait on both at the same time -- you don't want to be stuck waiting for a message in the socket if the user types a message; nor to be waiting for the user message while you have a new message from the network.

To 'wait' for messages from multiple streams, you have java.nio. I believe it is the most correct way of doing it.

But if you want to keep using the BufferedReader, there is a ready() method that returns true if and only if there is a message waiting to be read.

Your code after the in and stdIn declarations would then look something like (I didn't test it!!):

while(true) {
    if(stdIn.ready()) {
        System.out.println("I said " + stdIn.readLine());
    }
    if(in.ready()) (
        System.out.println("He said " + in.readLine());
    }
}

A few somewhat useful random links: