Creating a Mathematical Problem Solving Chat Application

Creating a Mathematical Problem Solving Chat Application

In this project, we will create a chat application where one computer acts as a server that solves mathematical problems, and other machines act as clients. Clients can send mathematical problems to the server, which will then solve the problems and send the results back to the clients.Before we start make sure you have connected your computers (server and clients) together, You can check how to do this in our previous post.

1. Designing the Protocol

We will design a simple protocol for our chat application with the following message types:

  • JOIN: Client joins the chat.
    Format: JOIN:username
  • SOLVE: Client sends a mathematical problem to the server.
    Format: SOLVE:problem
  • RESULT: Server sends the result of the solved problem to the client.
    Format: RESULT:solution
  • QUIT: Client leaves the chat.
    Format: QUIT:username

2. Implementing the Chat Server

The server will handle client connections, process mathematical problems, solve them, and send the results back to the clients. We will use a multi-threaded server with a thread pool to manage client connections efficiently.

Server Code

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;

public class MathServer {
    private static final int PORT = 8080;
    private static Set<ClientHandler> clientHandlers = ConcurrentHashMap.newKeySet();

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("Math server is listening on port " + PORT);

            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("New client connected");

                ClientHandler clientHandler = new ClientHandler(socket);
                clientHandlers.add(clientHandler);
                threadPool.execute(clientHandler);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    static void broadcast(String message, ClientHandler excludeClient) {
        for (ClientHandler clientHandler : clientHandlers) {
            if (clientHandler != excludeClient) {
                clientHandler.sendMessage(message);
            }
        }
    }

    static void removeClient(ClientHandler clientHandler) {
        clientHandlers.remove(clientHandler);
    }

    static class ClientHandler implements Runnable {
        private Socket socket;
        private PrintWriter writer;

        public ClientHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try (InputStream input = socket.getInputStream();
                 BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                 OutputStream output = socket.getOutputStream()) {

                writer = new PrintWriter(output, true);

                String message;
                while ((message = reader.readLine()) != null) {
                    String[] parts = message.split(":", 2);
                    String type = parts[0];
                    String content = parts[1];

                    switch (type) {
                        case "JOIN":
                            System.out.println(content + " joined the chat");
                            broadcast(content + " joined the chat", this);
                            break;
                        case "SOLVE":
                            System.out.println("Received problem: " + content);
                            String result = solveProblem(content);
                            sendMessage("RESULT:" + result);
                            break;
                        case "QUIT":
                            System.out.println(content + " left the chat");
                            broadcast(content + " left the chat", this);
                            break;
                    }
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                removeClient(this);
            }
        }

        void sendMessage(String message) {
            writer.println(message);
        }

        String solveProblem(String problem) {
            try {
                // Simple example: Solve factorial or simple equations like "2+2"
                if (problem.startsWith("factorial:")) {
                    int num = Integer.parseInt(problem.split(":")[1]);
                    return String.valueOf(factorial(num));
                } else {
                    // Using script engine for simple math evaluation
                    ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
                    return String.valueOf(engine.eval(problem));
                }
            } catch (Exception e) {
                return "Error solving problem: " + e.getMessage();
            }
        }

        int factorial(int n) {
            if (n <= 1) return 1;
            else return n * factorial(n - 1);
        }
    }
}

    

3. Implementing the Chat Client

The client will connect to the server, send mathematical problems, and display the results received from the server.

Client Code

import java.io.*;
import java.net.*;
import java.util.Scanner;

public class MathClient {
    private static String hostname = "localhost";
    private static int port = 8080;

    public static void main(String[] args) {
        try (Socket socket = new Socket(hostname, port);
             PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {

            Scanner scanner = new Scanner(System.in);
            String username;

            System.out.print("Enter your username: ");
            username = scanner.nextLine();
            writer.println("JOIN:" + username);

            // Start a new thread for receiving messages from the server
            new Thread(() -> {
                try {
                    String serverMessage;
                    while ((serverMessage = reader.readLine()) != null) {
                        System.out.println(serverMessage);
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }).start();

            // Main thread for sending messages to the server
            String clientMessage;
            while (true) {
                System.out.print("Enter problem to solve (or 'quit' to exit): ");
                clientMessage = scanner.nextLine();
                if (clientMessage.equalsIgnoreCase("quit")) {
                    writer.println("QUIT:" + username);
                    break;
                } else {
                    writer.println("SOLVE:" + clientMessage);
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

    

Explanation

Here's a detailed explanation of the server and client code:

Math Server:

  • Listens for incoming connections using ServerSocket.
  • Creates a ClientHandler thread for each client connection.
  • Processes messages according to the protocol:
    • JOIN: Broadcasts a join message.
    • SOLVE: Solves the mathematical problem and sends the result back to the client.
    • QUIT: Broadcasts a quit message and removes the client.
  • Uses a thread pool to manage threads efficiently.

Math Client:

  • Connects to the server using a Socket.
  • Sends a JOIN message to join the chat.
  • Starts a new thread to listen for messages from the server and print them to the console.
  • The main thread reads user input from the console and sends SOLVE messages to the server for mathematical problems, and QUIT message to leave the chat.

Conclusion 🔚

By designing a simple protocol and implementing both the server and client, we’ve created a chat application where clients can send mathematical problems to a server, which then solves the problems and returns the results. This project demonstrates the use of sockets, multi-threading, and mathematical problem-solving in Java.

For further exploration, consider adding features such as support for more complex mathematical problems, user authentication, or a graphical user interface (GUI) to enhance the chat application.

Want to dive deeper into Java networking? Check out our previous posts:

Stay tuned for more insights and practical examples to enhance your Java programming skills! 💻🌐