From 09835ffb6d7015484052367602cf3620a8b96d2e Mon Sep 17 00:00:00 2001 From: SaraZoveydavian Date: Sun, 21 Jun 2026 23:03:45 +0330 Subject: [PATCH] all classes implementd --- .../chat/Client/ServerListener.java | 17 +++ .../university/chat/Client/chatClient.java | 123 +++++++++++++++++- .../university/chat/Server/ChatServer.java | 20 ++- .../university/chat/Server/ClientSession.java | 85 ++++++++++++ 4 files changed, 237 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/university/chat/Client/ServerListener.java b/src/main/java/com/university/chat/Client/ServerListener.java index b609d74..8f69760 100644 --- a/src/main/java/com/university/chat/Client/ServerListener.java +++ b/src/main/java/com/university/chat/Client/ServerListener.java @@ -1,10 +1,17 @@ package com.university.chat.Client; +import com.university.chat.Common.ChatMessage; +import com.university.chat.Common.FileMessage; + +import java.io.ObjectInputStream; + public class ServerListener implements Runnable{ // TODO: store the ObjectInputStream from the user socket // (this should be the same input stream the // chatClient created when connecting) + private ObjectInputStream objectInputStream; + @Override public void run() { try { @@ -13,6 +20,16 @@ public class ServerListener implements Runnable{ // - if it's a FileMessage -> print that a file was received // (filename + sender), it's already // saved to disk by the server. + + while (true) { + if (objectInputStream.readObject() instanceof ChatMessage chatMessage) { + System.out.println(chatMessage.getSender() + " : " + chatMessage.getContent()); + } + if (objectInputStream.readObject() instanceof FileMessage fileMessage) { + System.out.println(" a file received from " + fileMessage.getSender() + " : " + fileMessage.getFilename()); + } + } + } catch (Exception e){ System.out.println("Disconnected from server"); } diff --git a/src/main/java/com/university/chat/Client/chatClient.java b/src/main/java/com/university/chat/Client/chatClient.java index dae0bad..0c5d75e 100644 --- a/src/main/java/com/university/chat/Client/chatClient.java +++ b/src/main/java/com/university/chat/Client/chatClient.java @@ -1,7 +1,24 @@ package com.university.chat.Client; +import com.university.chat.Common.ChatMessage; +import com.university.chat.Common.FileMessage; + +import java.io.*; +import java.net.Socket; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Scanner; + +import static com.university.chat.Common.MessageType.*; + public class chatClient { - public static void main() { + + private static String username; + private static ObjectOutputStream objectOutputStream; + private static ObjectInputStream objectInputStream; + + public static void main(String[] args) { // TODO: Connecting to the server // 1. Create a socket and connect to the server // 2. Create an ObjectOutputStream (out) and ObjectInputStream (in) @@ -10,7 +27,42 @@ public class chatClient { // 3. Start a new Thread running a ServerListener(in) so incoming // messages are handled concurrently. - while (true){ + try { + Socket socket = new Socket("localhost", 5000); + objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); + objectOutputStream.flush(); + objectInputStream = new ObjectInputStream(socket.getInputStream()); + + Scanner scanner = new Scanner(System.in); + System.out.print("Enter your username: "); + username = scanner.nextLine().trim(); + + ChatMessage loginMsg = new ChatMessage(LOGIN, username, null, null); + objectOutputStream.writeObject(loginMsg); + objectOutputStream.flush(); + + Object response = objectInputStream.readObject(); + if (response instanceof ChatMessage chatResponse) { + if (chatResponse.getType() == LOGIN_SUCCESS) { + System.out.println("Login successful!"); + } else if (chatResponse.getType() == LOGIN_FAILED) { + System.out.println("Login failed: " + chatResponse.getContent()); + return; + } + } + + } catch (IOException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + ServerListener serverListener = new ServerListener(); + Thread thread = new Thread(serverListener); + thread.setDaemon(true); + thread.start(); + + while (true) { try { // TODO: Program loop — read a line from the console and act on it: // - "/msg " -> build & send a PRIVATE_MESSAGE @@ -21,9 +73,72 @@ public class chatClient { // and send it as a FileMessage // - anything else -> send a PUBLIC_MESSAGE // Remember to flush() the output stream after writeObject(). - } catch (Exception e){ + + Scanner scanner = new Scanner(System.in); + String input = scanner.nextLine(); + + if (input == null || input.trim().isEmpty()) { + continue; + } + + input = input.trim(); + + if (input.startsWith("/msg ")) { + String[] parts = input.split(" ", 3); + if (parts.length < 3) { + System.out.println("Usage: /msg "); + continue; + } + String receiver = parts[1]; + String message = parts[2]; + + ChatMessage privateMsg = new ChatMessage(PRIVATE_MESSAGE, username, receiver, message); + objectOutputStream.writeObject(privateMsg); + objectOutputStream.flush(); + } + else if (input.equals("/users")) { + ChatMessage userListRequest = new ChatMessage(USER_LIST, username, null, null); + objectOutputStream.writeObject(userListRequest); + objectOutputStream.flush(); + } + else if (input.startsWith("/sendfile ")) { + String[] parts = input.split(" ", 3); + if (parts.length < 3) { + System.out.println("Usage: /sendfile "); + continue; + } + + String receiver = parts[1]; + String filePath = parts[2]; + + Path path = Paths.get(filePath); + if (!Files.exists(path)) { + System.out.println("File not found: " + filePath); + continue; + } + + String filename = path.getFileName().toString(); + long fileSize = Files.size(path); + + System.out.println("Sending file: " + filename + " (" + fileSize + " bytes)"); + + byte[] fileData = Files.readAllBytes(path); + + FileMessage fileMsg = new FileMessage(username, receiver, filename, fileData); + objectOutputStream.writeObject(fileMsg); + objectOutputStream.flush(); + + System.out.println("File sent: " + filename); + } + else { + ChatMessage publicMsg = new ChatMessage(PUBLIC_MESSAGE, username, "all", input); + objectOutputStream.writeObject(publicMsg); + objectOutputStream.flush(); + } + + } catch (Exception e) { System.out.println("command failed: " + e.getMessage()); } } } -} +} \ No newline at end of file diff --git a/src/main/java/com/university/chat/Server/ChatServer.java b/src/main/java/com/university/chat/Server/ChatServer.java index b2a35ae..3d5a5cd 100644 --- a/src/main/java/com/university/chat/Server/ChatServer.java +++ b/src/main/java/com/university/chat/Server/ChatServer.java @@ -1,15 +1,27 @@ package com.university.chat.Server; +import java.io.IOException; +import java.net.ServerSocket; + public class ChatServer { // TODO: declare a single shared UserManager instance (static final) // This MUST be shared by all ClientSession threads so that // broadcasting and private messaging work correctly. + static final UserManager userManager = new UserManager(); public static void main(String[] args) { // TODO: Create a ServerSocket - - // TODO: In an infinite loop: - // accept an incoming client connection - // make a new thread running ClientSession for each user. + try (ServerSocket serverSocket = new ServerSocket(5000);) { + // TODO: In an infinite loop: + // accept an incoming client connection + // make a new thread running ClientSession for each user. + while (true) { + ClientSession clientSession = new ClientSession(serverSocket.accept(), userManager); + Thread thread = new Thread(clientSession); + thread.start(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } } } diff --git a/src/main/java/com/university/chat/Server/ClientSession.java b/src/main/java/com/university/chat/Server/ClientSession.java index f09d64a..0f46e88 100644 --- a/src/main/java/com/university/chat/Server/ClientSession.java +++ b/src/main/java/com/university/chat/Server/ClientSession.java @@ -4,16 +4,34 @@ import com.university.chat.Common.ChatMessage; import com.university.chat.Common.FileMessage; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.net.Socket; import java.nio.file.Files; +import static com.university.chat.Common.MessageType.*; +import static com.university.chat.Server.ChatServer.userManager; + public class ClientSession implements Runnable { private String username; + private ObjectOutputStream objectOutputStream; + private ObjectInputStream objectInputStream; + private UserManager userManager; + private Socket socket; public ClientSession(Socket socket, UserManager userManager) { // TODO : Create an ObjectOutputStream from socket.getOutputStream() // and an ObjectInputStream from socket.getInputStream(). + this.socket = socket; + this.userManager = userManager; + + try { + objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); + objectInputStream = new ObjectInputStream(socket.getInputStream()); + } catch (IOException e) { + throw new RuntimeException(e); + } } @Override @@ -29,17 +47,51 @@ public class ClientSession implements Runnable { // 6. Otherwise, create the user's folders with FileManager.createUserFolders(...) // and send back LOGIN_SUCCESS. + Object object = objectInputStream.readObject(); + + if (object instanceof ChatMessage chatMessage) { + if (chatMessage.getType() == LOGIN) { + username = chatMessage.getSender(); + if (userManager.addUser(username, this)) { + FileManager.createUserFolders(username); + ChatMessage successMsg = new ChatMessage(LOGIN_SUCCESS, "Server", username, "Welcome" + username); + objectOutputStream.writeObject(successMsg); + objectOutputStream.flush(); + } else { + ChatMessage failedMsg = new ChatMessage(LOGIN_FAILED, "Server", username, "this username ia already taken!"); + objectOutputStream.writeObject(failedMsg); + objectOutputStream.flush(); + socket.close(); + return; + } + } else { + ChatMessage failedMsg = new ChatMessage(LOGIN_FAILED, "Server", "anonymous", "LOGIN FIRST!"); + } + } else { + socket.close(); + return; + } + // TODO: Main message loop // In a loop, call in.readObject(), you can separate messages by their type: // - if it's a ChatMessage -> call handleChatMessage(msg) // - if it's a FileMessage -> call handleFileMessage(fileMsg) // Keep looping until the connection is closed (an exception will be thrown). + while (true) { + if (objectInputStream.readObject() instanceof ChatMessage chatMessage1) { + handleChatMessage(chatMessage1); + } else if (objectInputStream.readObject() instanceof FileMessage fileMessage) { + handleFileMessage(fileMessage); + } + } + } catch (Exception e) { System.out.println("Disconnected: " + username); } finally { // TODO: Remove the user from UserManager so they no longer // receive broadcasts or appear in users list + userManager.removeUser(username); } } @@ -48,12 +100,29 @@ public class ClientSession implements Runnable { switch (msg.getType()) { case PUBLIC_MESSAGE -> { // TODO: Broadcast this message to every connected client. + for (ClientSession session : userManager.getAllSessions()) { + session.objectOutputStream.writeObject(msg); + session.objectOutputStream.flush(); + } } case PRIVATE_MESSAGE -> { // TODO: Forward this message to the receiver user. + String receiver = msg.getReceiver(); + ClientSession receiverS = userManager.getUser(receiver); + if (receiverS != null) { + receiverS.objectOutputStream.writeObject(msg); + receiverS.objectOutputStream.flush(); + } else { + ChatMessage errorMsg = new ChatMessage(PUBLIC_MESSAGE, "Server", msg.getSender(), receiver + " is not online!"); + objectOutputStream.writeObject(errorMsg); + objectOutputStream.flush(); + } } case USER_LIST -> { // TODO: Reply to the requester with the list of online users. + ChatMessage userListMsg = new ChatMessage(USER_LIST, "Server", msg.getSender(), userManager.listUsers()); + objectOutputStream.writeObject(userListMsg); + objectOutputStream.flush(); } } } @@ -67,5 +136,21 @@ public class ClientSession implements Runnable { Files.write(recvPath, fileMsg.getData()); // TODO: Forward the received file-message to the destination user. + + String receiver = fileMsg.getReceiver(); + ClientSession receiverSession = userManager.getUser(receiver); + if (receiverSession != null) { + try { + receiverSession.objectOutputStream.writeObject(fileMsg); + receiverSession.objectOutputStream.flush(); + } catch (IOException e) { + System.out.println("Error sending file to " + receiver); + } + } else { + ChatMessage errorMsg = new ChatMessage(PUBLIC_MESSAGE, "Server", fileMsg.getSender(), receiver + " is not online!" + ); + objectOutputStream.writeObject(errorMsg); + objectOutputStream.flush(); + } } } \ No newline at end of file