3 Commits
Author SHA1 Message Date
Matin 33e1df80c3 finish 2026-06-16 19:53:02 +04:30
Matin bad3cc5eb4 implemet Server Listener + chat server + part of client session 2026-06-16 18:25:21 +04:30
Matin d7d52070d5 implement Chat message 2026-06-16 12:15:15 +04:30
4 changed files with 186 additions and 5 deletions
@@ -1,6 +1,15 @@
package com.university.chat.Client; 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{ public class ServerListener implements Runnable{
private ObjectInputStream in ;
public ServerListener(ObjectInputStream in) {
this.in = in ;
}
// TODO: store the ObjectInputStream from the user socket // TODO: store the ObjectInputStream from the user socket
// (this should be the same input stream the // (this should be the same input stream the
// chatClient created when connecting) // chatClient created when connecting)
@@ -8,6 +17,18 @@ public class ServerListener implements Runnable{
@Override @Override
public void run() { public void run() {
try { try {
Object obj =in.readObject() ;
if (obj instanceof ChatMessage)
{
ChatMessage msg = (ChatMessage) obj ;
System.out.println("from : " + msg.getSender() + " ->" +msg.getContent() );
}
else if(obj instanceof FileMessage)
{
FileMessage fmsg = (FileMessage) obj ;
System.out.println("from : " + fmsg.getSender() + "-> File Name : " + fmsg.getFilename());
}
// TODO: In an infinite loop read objects from the server // TODO: In an infinite loop read objects from the server
// - if it's a ChatMessage -> print "<sender>: <content>" // - if it's a ChatMessage -> print "<sender>: <content>"
// - if it's a FileMessage -> print that a file was received // - if it's a FileMessage -> print that a file was received
@@ -1,7 +1,33 @@
package com.university.chat.Client; package com.university.chat.Client;
import com.university.chat.Common.ChatMessage;
import com.university.chat.Common.FileMessage;
import com.university.chat.Common.MessageType;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
public class chatClient { public class chatClient {
public static void main() { public static void main() throws IOException {
Socket socket = new Socket("localhost" , 8080) ;
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()) ;
ObjectInputStream in = new ObjectInputStream(socket.getInputStream()) ;
Scanner scanner = new Scanner(System.in) ;
System.out.println("Enter Your UserName");
String username = scanner.nextLine() ;
ChatMessage logmsg = new ChatMessage(MessageType.LOGIN , username , null , null) ;
out.writeObject(logmsg);
out.flush();
ServerListener serverListener = new ServerListener(in) ;
Thread thread = new Thread(serverListener) ;
thread.start();
// TODO: Connecting to the server // TODO: Connecting to the server
// 1. Create a socket and connect to the server // 1. Create a socket and connect to the server
// 2. Create an ObjectOutputStream (out) and ObjectInputStream (in) // 2. Create an ObjectOutputStream (out) and ObjectInputStream (in)
@@ -12,6 +38,46 @@ public class chatClient {
while (true){ while (true){
try { try {
String message = scanner.nextLine() ;
if (message.startsWith("/msg"))
{
String[] part = message.split(" " , 3) ;
if (part.length >=3)
{
String receiver = part[1];
String messageText = part[2];
ChatMessage privetMsg = new ChatMessage(MessageType.PRIVATE_MESSAGE , username , receiver , messageText) ;
out.writeObject(privetMsg);
out.flush();
}
} else if (message.startsWith("/User")) {
ChatMessage userRequest = new ChatMessage(MessageType.USER_LIST , username , null , null) ;
out.writeObject(userRequest);
out.flush();
} else if (message.startsWith("/sendfile")) {
String[] part = message.split(" " , 3) ;
if (part.length>=3)
{
String receiver = part[1] ;
String path = part[2] ;
File file = new File(path) ;
if (file.exists() && file.isFile())
{
byte[] fileBytes = Files.readAllBytes(Paths.get(path)) ;
FileMessage fileMsg = new FileMessage(username ,receiver ,file.getName() , fileBytes);
out.writeObject(fileMsg);
out.flush();
}
else {
System.out.println("file does not exist !");
}
}
}
// TODO: Program loop — read a line from the console and act on it: // TODO: Program loop — read a line from the console and act on it:
// - "/msg <user> <text>" -> build & send a PRIVATE_MESSAGE // - "/msg <user> <text>" -> build & send a PRIVATE_MESSAGE
// - "/users" -> build & send a USER_LIST request // - "/users" -> build & send a USER_LIST request
@@ -1,12 +1,25 @@
package com.university.chat.Server; package com.university.chat.Server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ChatServer { public class ChatServer {
// TODO: declare a single shared UserManager instance (static final) // TODO: declare a single shared UserManager instance (static final)
private static final UserManager usermanager = new UserManager() ;
// This MUST be shared by all ClientSession threads so that // This MUST be shared by all ClientSession threads so that
// broadcasting and private messaging work correctly. // broadcasting and private messaging work correctly.
public static void main(String[] args) { public static void main(String[] args) throws IOException {
// TODO: Create a ServerSocket // TODO: Create a ServerSocket
ServerSocket serverSocket = new ServerSocket(8080) ;
while (true)
{
Socket socket = serverSocket.accept() ;
ClientSession clientSession = new ClientSession(socket , usermanager) ;
Thread thread = new Thread(clientSession) ;
thread.start();
}
// TODO: In an infinite loop: // TODO: In an infinite loop:
// accept an incoming client connection // accept an incoming client connection
@@ -2,23 +2,74 @@ package com.university.chat.Server;
import com.university.chat.Common.ChatMessage; import com.university.chat.Common.ChatMessage;
import com.university.chat.Common.FileMessage; import com.university.chat.Common.FileMessage;
import com.university.chat.Common.MessageType;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket; import java.net.Socket;
import java.nio.file.Files; import java.nio.file.Files;
public class ClientSession implements Runnable { public class ClientSession implements Runnable {
private String username; private String username;
private ObjectInputStream in;
private ObjectOutputStream out ;
private Socket socket ;
private UserManager userManager ;
public ClientSession(Socket socket, UserManager userManager) { public ClientSession(Socket socket, UserManager userManager) throws IOException {
// TODO : Create an ObjectOutputStream from socket.getOutputStream() // TODO : Create an ObjectOutputStream from socket.getOutputStream()
// and an ObjectInputStream from socket.getInputStream(). // and an ObjectInputStream from socket.getInputStream().
this.socket = socket ;
this.userManager = userManager ;
this.out = new ObjectOutputStream(socket.getOutputStream()) ;
out.flush();
this.in = new ObjectInputStream(socket.getInputStream()) ;
} }
@Override @Override
public void run() { public void run() {
try { try {
Object firstobj = in.readObject() ;
if (firstobj instanceof ChatMessage loginmsg && loginmsg.getType() == MessageType.LOGIN)
{
this.username = loginmsg.getSender() ;
if (userManager.addUser(username , this))
{
FileManager.createUserFolders(username);
out.writeObject(new ChatMessage(MessageType.LOGIN_SUCCESS, "SERVER", username, "Welcome " + username));
out.flush();
System.out.println("User logged in successfully: " + username);
}
else
{
out.writeObject(new ChatMessage(MessageType.LOGIN_FAILED , "SERVER" , null, "User Name Already Taken !" ));
}
}
else {
socket.close();
return;
}
while (true)
{
Object obj = in.readObject() ;
if (obj instanceof ChatMessage chatMessage)
{
handleChatMessage(chatMessage);
}
else if (obj instanceof FileMessage fileMessage)
{
handleFileMessage(fileMessage);
}
}
// TODO: Welcome the user (login step) // TODO: Welcome the user (login step)
// 1. Read the first object sent by the client. // 1. Read the first object sent by the client.
@@ -38,8 +89,10 @@ public class ClientSession implements Runnable {
} catch (Exception e) { } catch (Exception e) {
System.out.println("Disconnected: " + username); System.out.println("Disconnected: " + username);
} finally { } finally {
// TODO: Remove the user from UserManager so they no longer if (username != null) {
// receive broadcasts or appear in users list userManager.removeUser(username);
}
} }
} }
@@ -48,13 +101,29 @@ public class ClientSession implements Runnable {
switch (msg.getType()) { switch (msg.getType()) {
case PUBLIC_MESSAGE -> { case PUBLIC_MESSAGE -> {
// TODO: Broadcast this message to every connected client. // TODO: Broadcast this message to every connected client.
for (ClientSession clientSession : userManager.getAllSessions())
{
clientSession.sendMessage(msg);
}
} }
case PRIVATE_MESSAGE -> { case PRIVATE_MESSAGE -> {
// TODO: Forward this message to the receiver user. // TODO: Forward this message to the receiver user.
ClientSession receiverSession = userManager.getUser(msg.getReceiver()) ;
if (receiverSession != null)
{
receiverSession.sendMessage(msg);
}
else {
sendMessage(new ChatMessage(MessageType.PRIVATE_MESSAGE, "SERVER", username, "User " + msg.getReceiver() + " is offline."));
}
} }
case USER_LIST -> { case USER_LIST -> {
// TODO: Reply to the requester with the list of online users. // TODO: Reply to the requester with the list of online users.
String userList = userManager.listUsers() ;
sendMessage(new ChatMessage(MessageType.USER_LIST , "SERVER" , username ,userList ));
} }
default -> {}
} }
} }
@@ -65,7 +134,19 @@ public class ClientSession implements Runnable {
Files.write(sentPath, fileMsg.getData()); Files.write(sentPath, fileMsg.getData());
Files.write(recvPath, fileMsg.getData()); Files.write(recvPath, fileMsg.getData());
ClientSession receiverSession = userManager.getUser(fileMsg.getReceiver());
if (receiverSession != null) {
receiverSession.sendFile(fileMsg);
}
// TODO: Forward the received file-message to the destination user. // TODO: Forward the received file-message to the destination user.
} }
public synchronized void sendMessage(ChatMessage msg) throws IOException {
out.writeObject(msg);
out.flush();
}
public synchronized void sendFile(FileMessage fileMsg) throws IOException {
out.writeObject(fileMsg);
out.flush();
}
} }