From db9b41b19042e4152ec315c9315cf69a61f2996a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Thu, 27 Feb 2025 22:04:11 +0100 Subject: [PATCH] established connection between Client and Serveur, setting up basic interactions --- ChatApp/src/ChatApp.java | 8 ++- ChatApp/src/client/Client.java | 28 +++++++- ChatApp/src/client/ClientConnexion.java | 16 ++++- .../packets/ServerResponsePacket.java | 2 +- ChatApp/src/server/Server.java | 66 ++++++++++++++++--- ChatApp/src/server/ServerConnexion.java | 34 ++++++++-- ClientServeur/src/Client.java | 23 ++++++- ClientServeur/src/Server.java | 4 ++ 8 files changed, 160 insertions(+), 21 deletions(-) diff --git a/ChatApp/src/ChatApp.java b/ChatApp/src/ChatApp.java index 872047b..0c0c9ab 100644 --- a/ChatApp/src/ChatApp.java +++ b/ChatApp/src/ChatApp.java @@ -1,4 +1,5 @@ import java.net.InetSocketAddress; +import java.util.Scanner; import client.Client; import server.Server; @@ -8,8 +9,13 @@ public class ChatApp { Server server = new Server(6665); Client client = new Client(new InetSocketAddress("localhost", 6665)); - while (true) { + client.SendCreateRoom("Room1"); + client.RequestRoomList(); + while (true) { + Scanner scan = new Scanner(System.in); + String message = scan.nextLine(); + client.SendChatMessage(message); } } } diff --git a/ChatApp/src/client/Client.java b/ChatApp/src/client/Client.java index 2b30fcb..4946423 100644 --- a/ChatApp/src/client/Client.java +++ b/ChatApp/src/client/Client.java @@ -5,13 +5,21 @@ import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; -import network.protocol.packets.LoginPacket; -import network.protocol.packets.SendChatMessagePacket; +import network.protocol.packets.*; public class Client { private final ClientConnexion connexion; + public static void main(String[] args) { + try { + Client client = new Client(new InetSocketAddress("localhost", 6665)); + client.SendChatMessage("Hello"); + } catch (SocketException e) { + e.printStackTrace(); + } + } + public Client(InetSocketAddress serverAddress) throws SocketException { this.connexion = new ClientConnexion(new DatagramSocket(), serverAddress); login("Moi"); @@ -32,4 +40,20 @@ public class Client { e.printStackTrace(); } } + + public void SendCreateRoom(String roomName) { + try { + this.connexion.sendPacket(new CreateRoomPacket(roomName)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void RequestRoomList() { + try { + this.connexion.sendPacket(new RequestRoomListPacket()); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/ChatApp/src/client/ClientConnexion.java b/ChatApp/src/client/ClientConnexion.java index 1d22351..0c30ed6 100644 --- a/ChatApp/src/client/ClientConnexion.java +++ b/ChatApp/src/client/ClientConnexion.java @@ -3,6 +3,7 @@ package client; import java.io.IOException; import java.net.DatagramSocket; import java.net.InetSocketAddress; +import java.time.Instant; import network.PacketHandler; import network.SocketReader; @@ -47,7 +48,14 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{ @Override public void visitPacket(ChatMessagePacket packet) { - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + StringBuilder sb = new StringBuilder(); + String time = packet.getTime().toString(); + sb.append(time, 11, 19); // We only take the HH:MM:SS part + sb.append(" "); + sb.append(packet.getChatter()); + sb.append(" : "); + sb.append(packet.getContent()); + System.out.println(sb); } @Override @@ -77,8 +85,12 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{ @Override public void visitPacket(RoomListPacket packet) { - System.out.println("Handled room list !"); + // System.out.println("Handled room list !"); // throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + System.out.println("Rooms :"); + for (String room : packet.getRoomNames()) { + System.out.println("\t" + room); + } } @Override diff --git a/ChatApp/src/network/protocol/packets/ServerResponsePacket.java b/ChatApp/src/network/protocol/packets/ServerResponsePacket.java index e45f73d..608c7b5 100644 --- a/ChatApp/src/network/protocol/packets/ServerResponsePacket.java +++ b/ChatApp/src/network/protocol/packets/ServerResponsePacket.java @@ -9,7 +9,7 @@ public class ServerResponsePacket extends Packet { static private final long serialVersionUID = Packets.Login.ordinal(); public static enum Response { - AuthSuccess, AuthError, RoomCreated, RoomNotCreated, RoomJoined, RoomNotJoined, NotInRoom; + AuthSuccess, AuthError, RoomCreated, RoomNotCreated, RoomJoined, RoomNotJoined, NotInRoom, RoomLeft, RoomNotLeft, messageSent, messageNotSent; }; private final Response response; diff --git a/ChatApp/src/server/Server.java b/ChatApp/src/server/Server.java index c7acc6b..4cfa332 100644 --- a/ChatApp/src/server/Server.java +++ b/ChatApp/src/server/Server.java @@ -3,6 +3,7 @@ package server; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -10,23 +11,75 @@ import java.util.Map; import network.PacketHandler; import network.SocketReader; import network.protocol.Packet; +import network.protocol.Packets; +import network.protocol.packets.ChatMessagePacket; +import network.protocol.packets.SendChatMessagePacket; +import network.protocol.packets.ServerResponsePacket; public class Server implements PacketHandler { private final DatagramSocket serverSocket; private final Map connexions; private final SocketReader reader; - private final ArrayList roomNames; + private final Map> roomNames; public Server(int port) throws SocketException { this.serverSocket = new DatagramSocket(port); this.connexions = new HashMap<>(); this.reader = new SocketReader(serverSocket, this); - this.roomNames = new ArrayList<>(); + this.roomNames = new HashMap<>(); } public ArrayList getRoomNames() { - return roomNames; + return roomNames.keySet().stream().collect(ArrayList::new, ArrayList::add, ArrayList::addAll); + } + + public String getRoomName(ServerConnexion connexion) { + for (Map.Entry> entry : roomNames.entrySet()) { + if(entry.getValue().contains(connexion)) { + return entry.getKey(); + } + } + return null; + } + + public void createRoom(String roomName, ServerConnexion connexion) throws SocketException { + if(roomNames.containsKey(roomName)) { + throw new SocketException("Room already exists"); + } + roomNames.put(roomName, new ArrayList<>()); + roomNames.get(roomName).add(connexion); + } + + public void leaveRoom(ServerConnexion connexion) throws SocketException { + String roomName = getRoomName(connexion); + if(roomName != null) { + roomNames.get(roomName).remove(connexion); + // Remove the room if it is empty + if(roomNames.get(roomName).isEmpty()) { + roomNames.remove(roomName); + } + return; + } + throw new SocketException("Room does not exist"); + } + + public void joinRoom(String roomName, ServerConnexion connexion) throws SocketException { + if(roomNames.containsKey(roomName)) { + roomNames.get(roomName).add(connexion); + return; + } + throw new SocketException("Room does not exist"); + } + + public void sendToRoom(ServerConnexion connexion, SendChatMessagePacket packet) throws SocketException { + String roomName = getRoomName(connexion); + ChatMessagePacket chatPacket = new ChatMessagePacket(Instant.now(), connexion.getChatterName(), packet.getContent()); + if(roomName != null && roomNames.containsKey(roomName)) { + roomNames.get(roomName).forEach(con -> con.sendPacket(chatPacket)); + return; + } + throw new SocketException("You are not in a room or the room does not exist"); } public void close() { @@ -34,11 +87,8 @@ public class Server implements PacketHandler { } public boolean hasChatterName(String pseudo) { - for (var entry : this.connexions.entrySet()) { - if (pseudo.equals(entry.getValue().getChatterName())) - return true; - } - return false; + return this.connexions.values().stream() + .anyMatch(connexion -> pseudo.equals(connexion.getChatterName())); } @Override diff --git a/ChatApp/src/server/ServerConnexion.java b/ChatApp/src/server/ServerConnexion.java index 2cb0416..a396963 100644 --- a/ChatApp/src/server/ServerConnexion.java +++ b/ChatApp/src/server/ServerConnexion.java @@ -3,6 +3,7 @@ package server; import java.io.IOException; import java.net.DatagramSocket; import java.net.InetSocketAddress; +import java.net.SocketException; import network.SocketWriter; import network.protocol.Packet; @@ -45,22 +46,38 @@ public class ServerConnexion implements PacketVisitor { @Override public void visitPacket(ChatMessagePacket packet) { + // I'm never supposed to receive this from the client throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); } @Override public void visitPacket(CreateRoomPacket packet) { - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + try { + server.createRoom(packet.getRoomName(), this); + sendPacket(new ServerResponsePacket(Response.RoomCreated)); + } catch (SocketException e) { + sendPacket(new ServerResponsePacket(Response.RoomNotCreated)); + } } @Override public void visitPacket(JoinRoomPacket packet) { - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + try { + server.joinRoom(packet.getRoomName(), this); + sendPacket(new ServerResponsePacket(Response.RoomJoined)); + } catch (SocketException e) { + sendPacket(new ServerResponsePacket(Response.RoomNotJoined)); + } } @Override public void visitPacket(LeaveRoomPacket packet) { - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + try { + server.leaveRoom(this); + sendPacket(new ServerResponsePacket(Response.RoomLeft)); + } catch (SocketException e) { + sendPacket(new ServerResponsePacket(Response.RoomNotLeft)); + } } @Override @@ -77,21 +94,28 @@ public class ServerConnexion implements PacketVisitor { @Override public void visitPacket(RequestRoomListPacket packet) { - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + sendPacket(new RoomListPacket(server.getRoomNames())); } @Override public void visitPacket(RoomListPacket packet) { + // I'm never supposed to receive this from the client throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); } @Override public void visitPacket(SendChatMessagePacket packet) { - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + try { + server.sendToRoom(this, packet); + sendPacket(new ServerResponsePacket(Response.messageSent)); + } catch (SocketException e) { + sendPacket(new ServerResponsePacket(Response.messageNotSent)); + } } @Override public void visitPacket(ServerResponsePacket packet) { + // I'm never supposed to receive this from the client throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); } diff --git a/ClientServeur/src/Client.java b/ClientServeur/src/Client.java index a2ed415..dd96eee 100644 --- a/ClientServeur/src/Client.java +++ b/ClientServeur/src/Client.java @@ -3,12 +3,31 @@ import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.util.Random; +import java.util.Scanner; public class Client { private final DatagramSocket socket; private final InetSocketAddress address; + public static void main(String[] args) throws IOException { + Scanner portScanner = new Scanner(System.in); + System.out.println("Enter the server port number: "); + int port = portScanner.nextInt(); + Client client = new Client(new InetSocketAddress("localhost", port)); + while(true) { + Scanner scan = new Scanner(System.in); + String message = scan.nextLine(); + client.sendMessage(message); + } + } + + + /** + * Create a new client + * @param address server adress (needed + * @throws IOException + */ public Client(InetSocketAddress address) throws IOException { this.address = address; this.socket = new DatagramSocket(); @@ -19,7 +38,7 @@ public class Client { private void sendGreetings() throws IOException { int random = new Random().nextInt(1000); String machineName = "RX" + random; - sendMessage("hello serveur " + machineName); + sendMessage("hello Serveur, I am " + machineName); } public void sendMessage(String message) throws IOException { @@ -32,7 +51,7 @@ public class Client { private void processHandshake(DatagramPacket packet) { String message = new String(packet.getData(), 0, packet.getLength()); String machineName = message.split(" ")[1]; - System.out.println("\t[Client] Serveur " + machineName + " ready: @" + packet.getAddress().getHostAddress() + ": " + System.out.println("↳[Client] Serveur " + machineName + " ready: @" + packet.getAddress().getHostAddress() + ": " + packet.getPort()); } diff --git a/ClientServeur/src/Server.java b/ClientServeur/src/Server.java index a9f1e0b..0fda501 100644 --- a/ClientServeur/src/Server.java +++ b/ClientServeur/src/Server.java @@ -13,6 +13,10 @@ public class Server { new Thread(this::readMessages).start(); } + public int getPort() { + return this.socket.getLocalPort(); + } + private void sendMessage(String message, InetAddress address, int port) throws IOException { byte[] buffer = message.getBytes(); DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, port);