Multi client chat application In java

Terchilă Marian :

I just got started with socket programming so in order to improve my understandings of it I wanna build a multi-client chat application.

They way I intend to do it is the following: Once the application starts you have two choices: create server or join server.

If you chose to create a server a new thread will start and host the server, then another thread will start which is gonna create a new client and automatically connect to the server just build.

And here I've encountered the following problem. Each client can send messages to the server, but in order to keep them synchronized for all clients I was thinking to redirect the retrieved messages from the server to all clients as shown in the following diagram. enter image description here

The thing is that when I try to listen and send on both client and server I get this errors.

java.net.SocketException: Connection reset
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:200)
    at java.base/java.io.DataInputStream.readUnsignedShort(DataInputStream.java:342)
    at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:594)
    at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:569)
    at parctice.Server.lambda$main$0(Server.java:32)
    at java.base/java.lang.Thread.run(Thread.java:835)

This is my server:

int port = 4444;

        try {
            ServerSocket serverSocket = new ServerSocket(port);
            System.out.println("server starts port = " + serverSocket.getLocalSocketAddress());


            while(true){
                Socket socket = serverSocket.accept();
                System.out.println("accepts : " + socket.getRemoteSocketAddress());

                DataInputStream in = new DataInputStream(socket.getInputStream());
                DataOutputStream out = new DataOutputStream(socket.getOutputStream());


                String[] message = {""};

                new Thread(() -> {
                    try {
                        while(in.available() > 0){
                            System.out.println("SERVER > " + in.readUTF());
                            message[0] = in.readUTF();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }).start();

                System.err.println(message[0]);
                try {
                    out.writeUTF(message[0] + "REDIRECTED MESSAGE");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

and my client:

int portNumber = 4444;
System.out.println("CLIENT >  Trying to connect to the server...");
try {
    Socket socket = new Socket("localhost", portNumber);

    DataInputStream in = new DataInputStream(socket.getInputStream());
    DataOutputStream out = new DataOutputStream(socket.getOutputStream());


    new Thread(() -> {
        try {
            while(in.available() > 0){
                System.out.println("SERVER > " + in.readUTF());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }).start();


    try {
        out.writeUTF("test");
    } catch (IOException e) {
        e.printStackTrace();
    }

} catch (IOException e) {
    e.printStackTrace();
}

In the end I would like to ask you guys if you think that the logic that I try to use is the right one and if not please let me know what's wrong and also if possible could you explain me why I am not being able to listen and send on both, client and server? Because when I try to send data through client and retrieve it on the server it works just fine, but I would like to accomplish both ways communication.

Terchilă Marian :

I've found this solution which seems to work for this scenario First time we create the server:

private List<ClientThread> clients; // or "protected static List<ClientThread> clients;"


public List<ClientThread> getClients(){
    return clients;
}
    private void startServer(){
        clients = new ArrayList<ClientThread>();
        try {
            serverSocket = new ServerSocket(PORT);
            System.out.println("SERVER ON");
            System.out.println("SERVER > Waiting for connections...");


//            ACCEPT ALL CONNECTIONS
            while (true){
                try {
                    Socket socket = serverSocket.accept();
                    System.out.println("SERVER > New connection: " + socket.getRemoteSocketAddress());
                    ClientThread client = new ClientThread(this, socket);
                    Thread thread = new Thread(client);
                    thread.start();
                    clients.add(client);
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("SERVER > Accept failed");
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Then for each client we create a new thread

public class ClientThread implements Runnable {

    private Socket socket;
    private Server server;
    private String clientName;

    public String getClientName() {
        return clientName;
    }

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public Socket getSocket() {
        return socket;
    }

    public void setSocket(Socket socket) {
        this.socket = socket;
    }

    public ClientThread(Server server, Socket socket) {
        this.server = server;
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            DataInputStream in = new DataInputStream(socket.getInputStream());
            DataOutputStream out = new DataOutputStream(socket.getOutputStream());

            out.writeUTF("HI FROM SERVER");
            while (!socket.isClosed()) {
                try {
                    if (in.available() > 0) {
                        String input = in.readUTF();
                        // UNCOMMENT TO READ ON SERVER
                        // System.out.println("SERVER > " + input);
                        for (ClientThread thatClient : server.getClients()){
                            DataOutputStream outputParticularClient = new DataOutputStream(thatClient.getSocket().getOutputStream());
                            outputParticularClient.writeUTF(input + " GOT FROM SERVER");
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client:

    public void createClient(){
        try {
            socket = new Socket("localhost", portNumber);
//            socket = new Socket(getHost(), portNumber);

            DataInputStream in = new DataInputStream(socket.getInputStream());
            new Thread(()->{
                while(!socket.isClosed()){
                    try {
                        if (in.available() > 0){
                            String input = in.readUTF();
                            System.out.println(getUserName() + " > " + input);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=163152&siteId=1