feat: add private message
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package clientserver.client;
|
package clientserver.client;
|
||||||
|
|
||||||
|
import clientserver.server.Server;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.DatagramPacket;
|
import java.net.DatagramPacket;
|
||||||
import java.net.DatagramSocket;
|
import java.net.DatagramSocket;
|
||||||
@@ -8,8 +9,6 @@ import java.net.SocketTimeoutException;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
import clientserver.server.Server;
|
|
||||||
|
|
||||||
public class Client {
|
public class Client {
|
||||||
|
|
||||||
InetAddress clientAddress;
|
InetAddress clientAddress;
|
||||||
@@ -27,6 +26,7 @@ public class Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class MessageReceiver implements Runnable {
|
private static class MessageReceiver implements Runnable {
|
||||||
|
|
||||||
private final DatagramSocket socket;
|
private final DatagramSocket socket;
|
||||||
private volatile boolean running = true;
|
private volatile boolean running = true;
|
||||||
|
|
||||||
@@ -43,21 +43,27 @@ public class Client {
|
|||||||
while (running && !socket.isClosed()) {
|
while (running && !socket.isClosed()) {
|
||||||
try {
|
try {
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
DatagramPacket packet = new DatagramPacket(
|
||||||
|
buffer,
|
||||||
|
buffer.length
|
||||||
|
);
|
||||||
|
|
||||||
socket.receive(packet);
|
socket.receive(packet);
|
||||||
String message = new String(packet.getData(), 0, packet.getLength());
|
String message = new String(
|
||||||
|
packet.getData(),
|
||||||
|
0,
|
||||||
|
packet.getLength()
|
||||||
|
);
|
||||||
|
|
||||||
// Afficher le message reçu avec une mise en forme claire
|
// Afficher le message reçu avec une mise en forme claire
|
||||||
System.out.println("\n>>> Message from server: \n" + message);
|
System.out.println(message);
|
||||||
System.out.print("Enter your message (or 'exit' to quit): ");
|
} catch (SocketTimeoutException e) {}
|
||||||
} catch (SocketTimeoutException e) {
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (!socket.isClosed()) {
|
if (!socket.isClosed()) {
|
||||||
System.err.println("Error in the reception of messages: " + e.getMessage());
|
System.err.println(
|
||||||
|
"Error in the reception of messages: " + e.getMessage()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("Message receiver stopped");
|
System.out.println("Message receiver stopped");
|
||||||
@@ -128,16 +134,23 @@ public class Client {
|
|||||||
System.out.println("Enter your Pseudo :");
|
System.out.println("Enter your Pseudo :");
|
||||||
|
|
||||||
// Créer le client avec l'adresse locale et le port du socket
|
// Créer le client avec l'adresse locale et le port du socket
|
||||||
Client client = new Client(socketClient.getLocalAddress(), socketClient.getLocalPort());
|
Client client = new Client(
|
||||||
|
socketClient.getLocalAddress(),
|
||||||
|
socketClient.getLocalPort()
|
||||||
|
);
|
||||||
client.setScanner(new Scanner(System.in));
|
client.setScanner(new Scanner(System.in));
|
||||||
String userPseudo = client.getScanner().next();
|
String userPseudo = client.getScanner().next();
|
||||||
client.setPseudo(userPseudo);
|
client.setPseudo(userPseudo);
|
||||||
|
|
||||||
System.out.println("Enter the IP address of the server :");
|
System.out.println("Enter the IP address of the server :");
|
||||||
try {
|
try {
|
||||||
client.serverAddress = InetAddress.getByName(client.getScanner().next());
|
client.serverAddress = InetAddress.getByName(
|
||||||
|
client.getScanner().next()
|
||||||
|
);
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
System.err.println("The address you choose create an UnknownHostException: " + e);
|
System.err.println(
|
||||||
|
"The address you choose create an UnknownHostException: " + e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Enter the port of the server:");
|
System.out.println("Enter the port of the server:");
|
||||||
@@ -146,26 +159,40 @@ public class Client {
|
|||||||
// (morph (/127.0.0.1:39056) : ...)
|
// (morph (/127.0.0.1:39056) : ...)
|
||||||
|
|
||||||
if (socketClient != null && client.serverAddress != null) {
|
if (socketClient != null && client.serverAddress != null) {
|
||||||
Server.sendMessage(socketClient, client.getPseudo(), client.serverAddress, client.getServerPort());
|
Server.sendMessage(
|
||||||
|
socketClient,
|
||||||
|
client.getPseudo(),
|
||||||
|
client.serverAddress,
|
||||||
|
client.getServerPort()
|
||||||
|
);
|
||||||
System.out.println("New connection request sent");
|
System.out.println("New connection request sent");
|
||||||
}
|
}
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void deconnexionClient(DatagramSocket socketClient, Client client, int handlerPort) {
|
private static void deconnexionClient(
|
||||||
|
DatagramSocket socketClient,
|
||||||
|
Client client,
|
||||||
|
int handlerPort
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
String disconnectMsg = "DISCONNECT";
|
String disconnectMsg = "/disconnect";
|
||||||
byte[] disconnectData = disconnectMsg.getBytes();
|
byte[] disconnectData = disconnectMsg.getBytes();
|
||||||
DatagramPacket disconnectPacket = new DatagramPacket(
|
DatagramPacket disconnectPacket = new DatagramPacket(
|
||||||
disconnectData,
|
disconnectData,
|
||||||
disconnectData.length,
|
disconnectData.length,
|
||||||
client.getServerAddress(),
|
client.getServerAddress(),
|
||||||
handlerPort);
|
handlerPort
|
||||||
|
);
|
||||||
socketClient.send(disconnectPacket);
|
socketClient.send(disconnectPacket);
|
||||||
System.out.println("Deconnection sended on the server port: " + handlerPort);
|
System.out.println(
|
||||||
|
"Deconnection sended on the server port: " + handlerPort
|
||||||
|
);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("Error during sending the deconnection message: " + e);
|
System.err.println(
|
||||||
|
"Error during sending the deconnection message: " + e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,18 +201,28 @@ public class Client {
|
|||||||
boolean running = true;
|
boolean running = true;
|
||||||
|
|
||||||
System.out.println("\n=== Chat client ready ===");
|
System.out.println("\n=== Chat client ready ===");
|
||||||
System.out.println("Type your messages then press 'Enter' to send them to the server.");
|
// System.out.println(
|
||||||
|
// "Type your messages then press 'Enter' to send them to the server."
|
||||||
|
// );
|
||||||
System.out.println("Type /list to see all the clients connected.");
|
System.out.println("Type /list to see all the clients connected.");
|
||||||
System.out.println("Type 'exit' to quit.");
|
System.out.println(
|
||||||
|
"Type '/msg <target> <message>' to send a private message."
|
||||||
|
);
|
||||||
|
System.out.println("Type '/help' to see all the commands.");
|
||||||
|
System.out.println("Type '/disconnect' to quit.\n");
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
System.out.print("Enter your message: ");
|
|
||||||
String message = this.getScanner().nextLine();
|
String message = this.getScanner().nextLine();
|
||||||
|
|
||||||
if ("exit".equalsIgnoreCase(message)) {
|
if ("/disconnect".equalsIgnoreCase(message)) {
|
||||||
running = false;
|
running = false;
|
||||||
} else {
|
} else {
|
||||||
Server.sendMessage(this.clientSocket, message, this.getServerAddress(), this.getHandlerPort());
|
Server.sendMessage(
|
||||||
|
this.clientSocket,
|
||||||
|
message,
|
||||||
|
this.getServerAddress(),
|
||||||
|
this.getHandlerPort()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +268,9 @@ public class Client {
|
|||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.err.println("Unexpected response from the server: " + reponse);
|
System.err.println(
|
||||||
|
"Unexpected response from the server: " + reponse
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8 - Libérer le canal
|
// 8 - Libérer le canal
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ public class ClientHandler implements Runnable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Client getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
if (clientHandlerSocket != null && !clientHandlerSocket.isClosed()) {
|
if (clientHandlerSocket != null && !clientHandlerSocket.isClosed()) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package clientserver.server;
|
package clientserver.server;
|
||||||
|
|
||||||
import clientserver.client.Client;
|
import clientserver.client.Client;
|
||||||
import java.net.DatagramPacket;
|
|
||||||
import java.net.DatagramSocket;
|
import java.net.DatagramSocket;
|
||||||
|
|
||||||
public class MessageProcessor {
|
public class MessageProcessor {
|
||||||
@@ -25,11 +24,84 @@ public class MessageProcessor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.equals("/list")) {
|
if (message.startsWith("/msg ")) {
|
||||||
handleListCommand();
|
handlePrivateMessage(message);
|
||||||
} else if (message.equals("DISCONNECT")) {
|
return;
|
||||||
handleDisconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
|
case "/list":
|
||||||
|
handleListCommand();
|
||||||
|
break;
|
||||||
|
case "/help":
|
||||||
|
handleHelpCommand();
|
||||||
|
break;
|
||||||
|
case "/msg":
|
||||||
|
handleMsgCommand();
|
||||||
|
break;
|
||||||
|
case "/disconnect":
|
||||||
|
handleDisconnect();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handlePrivateMessage(String message) {
|
||||||
|
String[] parts = message.split(" ", 3);
|
||||||
|
if (parts.length < 3) {
|
||||||
|
handleMsgCommand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String targetPseudo = parts[1];
|
||||||
|
String messageContent = parts[2];
|
||||||
|
|
||||||
|
ClientHandler targetHandler = Server.getClientHandler(targetPseudo);
|
||||||
|
|
||||||
|
if (targetHandler == null) {
|
||||||
|
Server.sendMessage(
|
||||||
|
clientHandlerSocket,
|
||||||
|
"> User " + targetPseudo + " not found",
|
||||||
|
client.getAddress(),
|
||||||
|
client.getPort()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send private message to target
|
||||||
|
Client targetClient = targetHandler.getClient();
|
||||||
|
Server.sendMessage(
|
||||||
|
clientHandlerSocket,
|
||||||
|
"> " +
|
||||||
|
client.getPseudo() +
|
||||||
|
" -> " +
|
||||||
|
targetClient.getPseudo() +
|
||||||
|
": " +
|
||||||
|
messageContent,
|
||||||
|
targetClient.getAddress(),
|
||||||
|
targetClient.getPort()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Send confirmation to sender
|
||||||
|
Server.sendMessage(
|
||||||
|
clientHandlerSocket,
|
||||||
|
"> " +
|
||||||
|
client.getPseudo() +
|
||||||
|
" -> " +
|
||||||
|
targetClient.getPseudo() +
|
||||||
|
": " +
|
||||||
|
messageContent,
|
||||||
|
client.getAddress(),
|
||||||
|
client.getPort()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleMsgCommand() {
|
||||||
|
Server.sendMessage(
|
||||||
|
clientHandlerSocket,
|
||||||
|
"> /msg <target> <message> : send a message to a client",
|
||||||
|
client.getAddress(),
|
||||||
|
client.getPort()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleListCommand() {
|
private void handleListCommand() {
|
||||||
@@ -41,6 +113,17 @@ public class MessageProcessor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleHelpCommand() {
|
||||||
|
Server.sendMessage(
|
||||||
|
clientHandlerSocket,
|
||||||
|
"> /list : list all connected clients" +
|
||||||
|
"\n> /msg <target> <message> : send a message to a client" +
|
||||||
|
"\n> /disconnect : disconnect from the server",
|
||||||
|
client.getAddress(),
|
||||||
|
client.getPort()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleDisconnect() {
|
private void handleDisconnect() {
|
||||||
System.out.println(
|
System.out.println(
|
||||||
"Client deconnection : " + ClientHandler.prettyPrint(client)
|
"Client deconnection : " + ClientHandler.prettyPrint(client)
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ public class Server {
|
|||||||
private int mainServerPort;
|
private int mainServerPort;
|
||||||
private DatagramSocket mainServerSocket;
|
private DatagramSocket mainServerSocket;
|
||||||
private boolean isRunning;
|
private boolean isRunning;
|
||||||
private static Map<String, ClientHandler> mapPseudosConnectedClientsHandlers = new ConcurrentHashMap<>();
|
private static Map<
|
||||||
|
String,
|
||||||
|
ClientHandler
|
||||||
|
> mapPseudosConnectedClientsHandlers = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public Server(int port) {
|
public Server(int port) {
|
||||||
this.mainServerPort = port;
|
this.mainServerPort = port;
|
||||||
@@ -45,7 +48,8 @@ public class Server {
|
|||||||
byte[] receivedData = new byte[1024];
|
byte[] receivedData = new byte[1024];
|
||||||
DatagramPacket receivedPacket = new DatagramPacket(
|
DatagramPacket receivedPacket = new DatagramPacket(
|
||||||
receivedData,
|
receivedData,
|
||||||
receivedData.length);
|
receivedData.length
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
socket.receive(receivedPacket); // Blocking call
|
socket.receive(receivedPacket); // Blocking call
|
||||||
@@ -57,81 +61,84 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String packetToMessage(DatagramPacket packet) {
|
public static String packetToMessage(DatagramPacket packet) {
|
||||||
return new String(
|
return new String(packet.getData(), 0, packet.getLength());
|
||||||
packet.getData(),
|
|
||||||
0,
|
|
||||||
packet.getLength());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendMessage(
|
public static void sendMessage(
|
||||||
DatagramSocket socket,
|
DatagramSocket socket,
|
||||||
String message,
|
String message,
|
||||||
java.net.InetAddress address,
|
java.net.InetAddress address,
|
||||||
int port) {
|
int port
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
byte[] sendData = message.getBytes();
|
byte[] sendData = message.getBytes();
|
||||||
DatagramPacket packetToSend = new DatagramPacket(
|
DatagramPacket packetToSend = new DatagramPacket(
|
||||||
sendData,
|
sendData,
|
||||||
sendData.length,
|
sendData.length,
|
||||||
address,
|
address,
|
||||||
port);
|
port
|
||||||
|
);
|
||||||
socket.send(packetToSend);
|
socket.send(packetToSend);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println(
|
System.err.println(
|
||||||
"Failed to send message to " + address + ":" + port);
|
"Failed to send message to " + address + ":" + port
|
||||||
|
);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNewConnection() {
|
private void handleNewConnection() {
|
||||||
DatagramPacket packet = receivedPacket(mainServerSocket);
|
DatagramPacket packet = receivedPacket(mainServerSocket);
|
||||||
if (packet == null)
|
if (packet == null) return;
|
||||||
return;
|
|
||||||
|
|
||||||
int originalClientPort = packet.getPort();
|
int originalClientPort = packet.getPort();
|
||||||
InetAddress clientAddress = packet.getAddress();
|
InetAddress clientAddress = packet.getAddress();
|
||||||
;
|
|
||||||
|
|
||||||
// Log the initial connection request
|
// Log the initial connection request
|
||||||
System.out.println(
|
System.out.println(
|
||||||
"New connection request from " +
|
"New connection request from " +
|
||||||
clientAddress +
|
clientAddress +
|
||||||
":" +
|
":" +
|
||||||
originalClientPort);
|
originalClientPort
|
||||||
|
);
|
||||||
|
|
||||||
// Process the received message
|
// Process the received message
|
||||||
String pseudoMessage = new String(packet.getData(), 0, packet.getLength());
|
String pseudoMessage = new String(
|
||||||
|
packet.getData(),
|
||||||
|
0,
|
||||||
|
packet.getLength()
|
||||||
|
);
|
||||||
|
|
||||||
System.out.println(
|
System.out.println(
|
||||||
"Received message from " +
|
"Received message from " +
|
||||||
clientAddress +
|
clientAddress +
|
||||||
":" +
|
":" +
|
||||||
originalClientPort +
|
originalClientPort +
|
||||||
": " +
|
": " +
|
||||||
pseudoMessage);
|
pseudoMessage
|
||||||
|
);
|
||||||
// Create a new socket for this client
|
// Create a new socket for this client
|
||||||
DatagramSocket clientHandlerSocket = createNewSocket();
|
DatagramSocket clientHandlerSocket = createNewSocket();
|
||||||
if (clientHandlerSocket == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (clientHandlerSocket == null) return;
|
||||||
int clientHandlerLocalPort = clientHandlerSocket.getLocalPort();
|
int clientHandlerLocalPort = clientHandlerSocket.getLocalPort();
|
||||||
|
|
||||||
Client client = new Client(clientAddress, originalClientPort);
|
Client client = new Client(clientAddress, originalClientPort);
|
||||||
client.setPseudo(pseudoMessage);
|
|
||||||
|
|
||||||
|
client.setPseudo(pseudoMessage);
|
||||||
// Send new port information to client
|
// Send new port information to client
|
||||||
String response = "PORT:" + clientHandlerLocalPort;
|
String response = "PORT:" + clientHandlerLocalPort;
|
||||||
|
|
||||||
sendMessage(
|
sendMessage(
|
||||||
mainServerSocket,
|
mainServerSocket,
|
||||||
response,
|
response,
|
||||||
clientAddress,
|
clientAddress,
|
||||||
packet.getPort());
|
packet.getPort()
|
||||||
|
);
|
||||||
// Create and start a ClientHandler for this connection
|
// Create and start a ClientHandler for this connection
|
||||||
ClientHandler handler = new ClientHandler(clientHandlerSocket, client);
|
ClientHandler handler = new ClientHandler(clientHandlerSocket, client);
|
||||||
|
|
||||||
Thread thread = new Thread(handler);
|
Thread thread = new Thread(handler);
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
||||||
// Add client handler to mapPseudosConnectedClients
|
// Add client handler to mapPseudosConnectedClients
|
||||||
addConnectedClientHandler(pseudoMessage, handler);
|
addConnectedClientHandler(pseudoMessage, handler);
|
||||||
}
|
}
|
||||||
@@ -143,7 +150,8 @@ public class Server {
|
|||||||
handleNewConnection();
|
handleNewConnection();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println(
|
System.err.println(
|
||||||
"Error handling connection: " + e.getMessage());
|
"Error handling connection: " + e.getMessage()
|
||||||
|
);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,12 +159,30 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getPseudos() {
|
public static String getPseudos() {
|
||||||
StringBuilder pseudos = new StringBuilder("All connected clients:\n");
|
StringBuilder pseudos = new StringBuilder();
|
||||||
mapPseudosConnectedClientsHandlers.forEach((k, v) -> pseudos.append("Pseudo: ").append(k).append("\n"));
|
int size = mapPseudosConnectedClientsHandlers.size();
|
||||||
|
int count = 0;
|
||||||
|
for (Map.Entry<
|
||||||
|
String,
|
||||||
|
ClientHandler
|
||||||
|
> entry : mapPseudosConnectedClientsHandlers.entrySet()) {
|
||||||
|
count++;
|
||||||
|
pseudos.append("> ").append(entry.getKey());
|
||||||
|
if (count < size) {
|
||||||
|
pseudos.append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
return pseudos.toString();
|
return pseudos.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConnectedClientHandler(String pseudo, ClientHandler clientHandler) {
|
public static ClientHandler getClientHandler(String pseudo) {
|
||||||
|
return mapPseudosConnectedClientsHandlers.get(pseudo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConnectedClientHandler(
|
||||||
|
String pseudo,
|
||||||
|
ClientHandler clientHandler
|
||||||
|
) {
|
||||||
mapPseudosConnectedClientsHandlers.putIfAbsent(pseudo, clientHandler);
|
mapPseudosConnectedClientsHandlers.putIfAbsent(pseudo, clientHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
gradle.properties
Normal file
1
gradle.properties
Normal file
@@ -0,0 +1 @@
|
|||||||
|
org.gradle.console=plain
|
||||||
Reference in New Issue
Block a user