why are the messages only being printed on client side of the GUI?

45 Views Asked by At

i have been working on a game called roborally. And we are supposed to establish a multiples Client chat. I want to know if my server or clientHandler aren't sending messages to the clients. im Using Java and JavaFx for the Gui.

this is my classes :

Client Class :


package com.roborally.chat_gui;

import javafx.scene.layout.VBox;

import java.io.*;
import java.net.Socket;
import java.util.ResourceBundle;
import java.util.Scanner;
/**
 * The Client class represents a client in the chat application. It manages the communication with the server,
 * including sending and receiving messages.
 */
public class Client {

    private String username;
    private Socket socket;
    private volatile BufferedWriter bufferedWriter;
    private volatile BufferedReader bufferedReader;
    private final VBox vBox;

    /**
     * Constructs a new Client with the specified username, socket, and VBox.
     *
     * @param username The username of the client.
     * @param socket   The socket representing the connection to the server.
     * @param vBox     The VBox for displaying messages in the user interface.
     */
    public Client(String username, Socket socket, VBox vBox) {
        this.username = username;
        this.vBox = vBox;
        try {
            this.socket = socket;
            this.bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            this.bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.username = username;

        }catch (IOException e){
            closeEverything(socket,bufferedReader,bufferedWriter);
            e.printStackTrace();

        }
    }
    /**
     * Sends a message from the client to the server.
     *
     * @param messageToSend The message to be sent.
     */
    public void sendMessage(String messageToSend) {
        try {
            bufferedWriter.write(messageToSend);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        } catch (IOException e) {
            closeEverything(socket, bufferedReader, bufferedWriter);
        } finally {
            // Close the BufferedWriter in a finally block
            try {
                if (bufferedWriter != null) {
                    bufferedWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * Listens for incoming messages from the server and displays them in the user interface.
     */
    public void receiveMessageFromClient(VBox vBox) {
        new Thread(() -> {
            while (socket.isConnected()) {
                try {
                    if (!socket.isClosed() && bufferedReader.ready()) {
                        String messageFromClient = bufferedReader.readLine();
                        if (messageFromClient == null) {
                            // Connection closed by the server
                            System.out.println("Server closed the connection");
                            break;
                        }
                        ClientController.addLabel(messageFromClient, vBox);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("Error receiving message from Client");
                    break;
                }
            }
        }).start();
    }
    /**
     * Closes all resources associated with the client.
     *
     * @param socket         The socket representing the connection to the server.
     * @param bufferedReader The BufferedReader for receiving messages from the server.
     * @param bufferedWriter The BufferedWriter for sending messages to the server.
     */
    public void closeEverything(Socket socket, BufferedReader bufferedReader, BufferedWriter bufferedWriter){
        try {
            if (bufferedWriter != null){
                bufferedWriter.close();
            }
            if (bufferedReader != null){
                bufferedReader.close();
            }
            if (socket != null){
                socket.close();
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

ClientHandler class :


package com.roborally.chat_gui;

import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
 * The ClientHandler class represents a handler for communication with a specific client in a chat application.
 * It manages the input and output streams for the client, listens for incoming messages, and broadcasts messages
 * from the client to all other connected clients.
 */
public class ClientHandler implements Runnable{

    public  List<ClientHandler> clientHandlers = new CopyOnWriteArrayList<>(); /* keep track of clients, allowing to communicate*/
    private  Socket socket;
    private BufferedReader bufferedReader; /* read data from the client */
    private BufferedWriter bufferedWriter;/* send messages from client to client*/
    private String clientUsername;
    private Server server;

    /**
     * Constructs a new ClientHandler for a connected client.
     *
     * @param socket         The socket representing the connection to the client.
     * @param clientHandlers The list of client handlers for keeping track of clients.
     * @param server         The reference to the server managing the communication.
     */
    public ClientHandler(Socket socket, List<ClientHandler> clientHandlers, Server server) {
        try {
            this.socket = socket;
            this.bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            this.bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.clientUsername = bufferedReader.readLine();
            this.server = server;
            clientHandlers.add(this);
            broadCastMessage("SERVER" + clientUsername + "has entered the chat  !");


        } catch (IOException e) {
            closeEverything();

        }
    }
    /**
     * Listens for incoming messages from the client and broadcasts them to all connected clients.
     * If the client disconnects, it handles the disconnection and breaks out of the loop.
     */
    @Override
    public void run() {
        String messageFromClient;

        while (socket.isConnected()){
            try {
                messageFromClient = bufferedReader.readLine();
                if (messageFromClient != null){
                    System.out.println("Received message from " + clientUsername + ": " + messageFromClient);
                    broadCastMessage(messageFromClient);
                }else {
                    disconnectClient();
                    break;
                }

            } catch (IOException e) {
                removeClientHandler();
                break;
            }
        }

    }
    /**
     * Gets the username of the client.
     *
     * @return The username of the client.
     */
    public String getClientUsername() {
        return clientUsername;
    }
    /**
     * Disconnects the client, removes it from the list of connected clients, and broadcasts a disconnection message.
     *
     * @throws IOException If an I/O error occurs during disconnection.
     */
    public void disconnectClient() throws IOException {
        clientHandlers.remove(this);
        server.disconnectClient(this);
        removeClientHandler();
    }
    /**
     * Sends a message from the client to all connected clients.
     *
     * @param message The message to be sent.
     * @throws IOException If an I/O error occurs during message sending.
     */
    public void sendMessageToClient(String message) throws IOException {
        if (socket.isConnected()) {
            bufferedWriter.write(message);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        } else {
            disconnectClient();
        }
    }
    /**
     * Broadcasts a message from the client to all other connected clients.
     *
     * @param messageToSend The message to be broadcasted.
     */
    public void broadCastMessage(String messageToSend) {
        for (ClientHandler clientHandler : clientHandlers) {
            try {
                if (!clientHandler.clientUsername.equals(clientUsername)) {
                    System.out.println("Sending message from " + clientUsername + " to " + clientHandler.clientUsername);
                    clientHandler.sendMessageToClient(messageToSend);
                    System.out.println("Message sent to " + clientHandler.clientUsername);
                }
            } catch (IOException e) {
                e.printStackTrace();
                closeEverything();
            }
        }
    }
    /**
     * Removes the client handler from the list of connected clients.
     */
    public void removeClientHandler() {
        clientHandlers.remove(this);
        server.removeClientWriter(bufferedWriter);
        broadCastMessage("Server" + clientUsername + " has left the chat !");
    }
    /**
     * Closes all resources associated with the client handler.
     */
    public  void closeEverything(){
        removeClientHandler();
        try {
            if (bufferedReader != null){
                bufferedReader.close();
            }
            if (bufferedWriter != null){
                bufferedWriter.close();
            }
            if (socket != null){
                socket.close();
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

**ClientController Class **:

package com.roborally.chat_gui;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
import java.util.ResourceBundle;
/**
 * The ClientController class manages the interaction between the user interface and the Client.
 */
public class ClientController implements Initializable {
    @FXML
    private Button button_send;
    @FXML
    private TextField message;
    @FXML
    private VBox Vbox_messages;
    @FXML
    private ScrollPane sp_main;
    private Client client;
    /**
     * Initializes the controller, creating a new Client instance and setting up event handlers.
     */
    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        try {
            String username = "YourUsername";
            VBox vBox = Vbox_messages;
            client = new Client(username, new Socket("localhost", 8080), vBox);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Error creating Client. ");
        }

        Vbox_messages.heightProperty().addListener((observableValue, number, newValue) -> {
            sp_main.setVvalue((Double) newValue);
        });

        button_send.setOnAction(event -> {
            Platform.runLater(() -> {
                String messageToSend = message.getText();
                if (!messageToSend.isEmpty()) {
                    HBox hBox = new HBox();
                    hBox.setAlignment(Pos.CENTER_RIGHT);
                    hBox.setPadding(new Insets(5, 5, 5, 10));

                    Text text = new Text(messageToSend);
                    TextFlow textFlow = new TextFlow(text);

                    textFlow.setStyle("-fx-color: rgb(239,242,255); " +
                            "-fx-background-color: rgb(15,125,242);" +
                            " -fx-background-radius: 20px");
                    textFlow.setPadding(new Insets(5, 10, 5, 10));
                    text.setFill(Color.color(0.934, 0.945, 0, 0.966));
                    hBox.getChildren().add(textFlow);
                    Vbox_messages.getChildren().add(hBox);
                    client.sendMessage(messageToSend);
                    message.clear();
                }
            });
        });

        client.receiveMessageFromClient(Vbox_messages);
    }
    /**
     * Adds a label to the user interface for messages received from the server.
     *
     * @param messageFromClient The message received from the server.
     * @param vBox              The VBox for displaying messages in the user interface.
     */

    public static void addLabel(String messageFromClient, VBox vBox) {
        HBox hBox = new HBox();
        hBox.setAlignment(Pos.CENTER_LEFT);
        hBox.setPadding(new Insets(5, 5, 5, 10));
        Text text = new Text(messageFromClient);
        TextFlow textFlow = new TextFlow(text);
        textFlow.setStyle("-fx-color: rgb(233,233,235);" +
                "-fx-background-radius: 20px");
        textFlow.setPadding(new Insets(5, 10, 5, 10));
        hBox.getChildren().add(textFlow);

        Platform.runLater(() -> {
            vBox.getChildren().add(hBox);
        });
    }
}

And my Server cLass :

package com.roborally.chat_gui;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * The Server class manages the communication between clients in a chat application.
 * It accepts incoming client connections and creates a separate {@link ClientHandler} thread for each client.
 * The server handles client disconnections and broadcasts disconnection messages to all connected clients.
 */
public class Server {

    private ServerSocket serverSocket;
    private List<PrintWriter> clientWriters = new CopyOnWriteArrayList<>();
    private List<ClientHandler> clientHandlers = new CopyOnWriteArrayList<>();

    /**
     * Constructs a new Server with the given ServerSocket.
     *
     * @param serverSocket The ServerSocket to accept client connections.
     */
    public Server(ServerSocket serverSocket) {
        this.serverSocket = serverSocket;
    }
    /**
     * Starts the server by initiating the thread to accept incoming clients.
     */
    public void startServer() {
        new Thread(this::acceptClients).start();
    }
    /**
     * Accepts incoming client connections and creates a ClientHandler thread for each client.
     */
    private void acceptClients() {
        try {
            while (!serverSocket.isClosed()) {
                Socket socket = serverSocket.accept();
                System.out.println("A new Client has connected !");
                ClientHandler clientHandler = new ClientHandler(socket, clientHandlers, this);
                clientHandlers.add(clientHandler);
                Thread thread = new Thread(clientHandler);
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * Disconnects the specified client and broadcasts a disconnection message to all clients.
     *
     * @param clientHandler The ClientHandler representing the client to be disconnected.
     * @throws IOException If an I/O error occurs during disconnection.
     */
    public void disconnectClient(ClientHandler clientHandler) throws IOException {
        clientHandlers.remove(clientHandler);
        broadcastDisconnectionMessage(clientHandler.getClientUsername());
    }
    /**
     * Broadcasts a disconnection message to all connected clients.
     *
     * @param username The username of the client that has disconnected.
     * @throws IOException If an I/O error occurs during message broadcasting.
     */
    private void broadcastDisconnectionMessage(String username) throws IOException {
        String message = "Server: " + username + " has left the chat!";
        for (ClientHandler handler : clientHandlers) {
            handler.sendMessageToClient(message);
        }
    }
    /**
     * Removes the specified client's writer from the list of client writers.
     *
     * @param writer The BufferedWriter of the client to be removed.
     */
    public void removeClientWriter(BufferedWriter writer) {
        clientWriters.remove(writer);
    }
    /**
     * The main method to start the server. It creates a ServerSocket on the specified port and starts the server.
     *
     * @param args Command-line arguments (not used).
     * @throws IOException If an I/O error occurs during server initialization.
     */
    public static void main (String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        Server server = new Server(serverSocket);
        server.startServer();
    }
}

0

There are 0 best solutions below