diff --git a/.project b/.project
new file mode 100644
index 0000000..9f05120
--- /dev/null
+++ b/.project
@@ -0,0 +1,28 @@
+
+
+ ClientServer
+ Project ClientServer created by Buildship.
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1743445961452
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 0000000..d230334
--- /dev/null
+++ b/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,13 @@
+arguments=--init-script /home/xeon0x/.var/app/dev.zed.Zed/data/zed/extensions/work/java/jdtls/jdt-language-server-1.46.0-202503271314/configuration/org.eclipse.osgi/58/0/.cp/gradle/init/init.gradle
+auto.sync=false
+build.scans.enabled=false
+connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
+connection.project.dir=
+eclipse.preferences.version=1
+gradle.user.home=
+java.home=/usr/lib64/jvm/java-21-openjdk-21
+jvm.arguments=
+offline.mode=false
+override.workspace.settings=true
+show.console.view=true
+show.executions.view=true
diff --git a/README.md b/README.md
index c940f86..2d82657 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,39 @@
+# ClientServer
+
+## Build
+
+```bash
+./gradlew build
+```
+
+## Run
+
+### Client
+
+```bash
+./gradlew run --args='client'
+```
+
+or
+
+```bash
+./gradlew runServer
+```
+
+### Server
+
+```bash
+./gradlew run --args='server'
+```
+
+or
+
+```bash
+./gradlew runServer
+```
+
+## Documentation
+
```mermaid
sequenceDiagram
Note over Client, Serveur: DatagramSocket("localhost", 66666)
diff --git a/app/.classpath b/app/.classpath
new file mode 100644
index 0000000..282ada5
--- /dev/null
+++ b/app/.classpath
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/.project b/app/.project
new file mode 100644
index 0000000..ecb5e8f
--- /dev/null
+++ b/app/.project
@@ -0,0 +1,34 @@
+
+
+ app
+ Project app created by Buildship.
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1743445961456
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/app/.settings/org.eclipse.buildship.core.prefs b/app/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 0000000..b1886ad
--- /dev/null
+++ b/app/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/app/build.gradle b/app/build.gradle
index 990d74d..fc08b4d 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -40,3 +40,19 @@ tasks.named('test') {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}
+
+task runServer(type: JavaExec) {
+ description = 'Runs the server'
+ group = 'application'
+ mainClass = application.mainClass
+ classpath = sourceSets.main.runtimeClasspath
+ args = ['--server']
+}
+
+task runClient(type: JavaExec) {
+ description = 'Runs the client'
+ group = 'application'
+ mainClass = application.mainClass
+ classpath = sourceSets.main.runtimeClasspath
+ args = ['--client']
+}
diff --git a/app/src/main/java/clientserver/App.java b/app/src/main/java/clientserver/App.java
index 94a7196..658a06e 100644
--- a/app/src/main/java/clientserver/App.java
+++ b/app/src/main/java/clientserver/App.java
@@ -1,5 +1,8 @@
package clientserver;
+import clientserver.client.Client;
+import clientserver.server.Server;
+
public class App {
public String getGreeting() {
@@ -7,8 +10,49 @@ public class App {
}
public static void main(String[] args) {
- System.out.println(new App().getGreeting());
- ClientHandler.main(new String[] {});
- // MistralDirectAPI.main(new String[] {});
+ String mode = null;
+
+ // Parse arguments
+ for (String arg : args) {
+ switch (arg.toLowerCase()) {
+ case "--client":
+ mode = "client";
+ break;
+ case "--server":
+ mode = "server";
+ break;
+ default:
+ System.out.println("Unknown argument: " + arg);
+ printUsage();
+ return;
+ }
+ }
+
+ // Check if mode is specified
+ if (mode == null) {
+ System.out.println("No mode specified.");
+ printUsage();
+ return;
+ }
+
+ // Execute based on mode
+ switch (mode) {
+ case "client":
+ System.out.println("Starting client...");
+ Client.main(new String[] {});
+ break;
+ case "server":
+ System.out.println("Starting server...");
+ Server server = new Server(6666);
+ server.run();
+ break;
+ }
+ }
+
+ private static void printUsage() {
+ System.out.println("Usage: ./gradlew run --args='option'");
+ System.out.println("Options:");
+ System.out.println(" --client Run in client mode");
+ System.out.println(" --server Run in server mode");
}
}
diff --git a/app/src/main/java/clientserver/Client.java b/app/src/main/java/clientserver/Client.java
deleted file mode 100644
index e209afa..0000000
--- a/app/src/main/java/clientserver/Client.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package clientserver;
-
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-
-public class Client {
- public static void main(String[] args) {
- try {
- // 1 - Création du canal avec un port libre
- DatagramSocket socketClient = new DatagramSocket();
- InetAddress adresseServeur = InetAddress.getByName("localhost");
- int portServeur = 6666;
-
- // 2 - Envoyer un message au serveur
- String message = "Hello Server";
- byte[] envoyees = message.getBytes();
- DatagramPacket paquetEnvoye = new DatagramPacket(
- envoyees, envoyees.length, adresseServeur, portServeur);
- socketClient.send(paquetEnvoye);
- System.out.println("Message envoyé au serveur");
-
- // 3 - Recevoir
- byte[] recues = new byte[1024]; // tampon de réception
- DatagramPacket paquetRecu = new DatagramPacket(recues, recues.length);
- socketClient.receive(paquetRecu);
- String reponse = new String(paquetRecu.getData(), 0, paquetRecu.getLength());
-
- if (reponse.startsWith("PORT:")) {
- int newPort = Integer.parseInt(reponse.substring(5));
-
- System.out.println("Connexion au nouveau port: " + newPort);
-
- // 4 - Communiquer sur le nouveau port
- String messagePort = "Message au nouveau port";
- byte[] envoyeesPort = messagePort.getBytes();
- DatagramPacket paquetPort = new DatagramPacket(
- envoyeesPort, envoyeesPort.length, adresseServeur, newPort);
- socketClient.send(paquetPort);
- }
-
- // 5 - Libérer le canal
- socketClient.close();
- } catch (Exception e) {
- System.err.println(e);
- }
- }
-}
diff --git a/app/src/main/java/clientserver/ClientHandler.java b/app/src/main/java/clientserver/ClientHandler.java
deleted file mode 100644
index a9aa42d..0000000
--- a/app/src/main/java/clientserver/ClientHandler.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package clientserver;
-
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-
-public class ClientHandler {
-
- static void main(String[] args) {
- int port = 6666;
- boolean running = true;
- DatagramSocket socketServer = null;
- try {
- socketServer = new DatagramSocket(null);
- // 2 - Réservation du port
- InetSocketAddress address = new InetSocketAddress(
- "localhost",
- port
- );
- socketServer.bind(address);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- while (running) {
- try {
- // 1 - Création du canal
-
- // 3 - Recevoir
- byte[] recues = new byte[1024]; // tampon de réception
- DatagramPacket receivedPacket = new DatagramPacket(
- recues,
- recues.length
- );
- socketServer.receive(receivedPacket);
- InetAddress clientAddress = receivedPacket.getAddress();
- int clientPort = receivedPacket.getPort();
- System.out.println(
- "Nouveau client : @" + clientAddress + ":" + clientPort
- );
- DatagramSocket socket = new DatagramSocket(); // Reserve new port
-
- String response = "PORT:" + socket.getLocalPort();
- System.out.println(response);
- byte[] envoyees; // tampon d'émission
- envoyees = response.getBytes();
- DatagramPacket packetToSend = new DatagramPacket(
- envoyees,
- envoyees.length,
- clientAddress,
- clientPort
- );
- socketServer.send(packetToSend);
- Thread thread = new Thread(() -> createThread(socket));
- thread.start();
- } catch (Exception e) {
- System.err.println(e);
- }
- }
-
- socketServer.close();
- }
-
- public static void createThread(DatagramSocket socketClientThread) {
- try {
- byte[] recues = new byte[1024]; // tampon de réception
- DatagramPacket receivedPacket = new DatagramPacket(
- recues,
- recues.length
- );
- socketClientThread.receive(receivedPacket);
- String message = new String(
- receivedPacket.getData(),
- 0,
- receivedPacket.getLength()
- );
- System.out.println("Received message: " + message);
- } catch (Exception e) {
- System.err.println(e);
- }
- }
-
- static void scannerUDP(int startPort, int endPort) {
- try {
- for (int i = startPort; i < endPort; i++) {
- try (DatagramSocket socket = new DatagramSocket(i)) {} catch (
- Exception e
- ) {
- System.out.println("Port n°" + i + " déjà occupé");
- }
- }
- } catch (Exception e) {
- System.out.println(e);
- }
- }
- // public static void main(String[] args) {
- // try {
- // // 1 - Création du canal
- // DatagramSocket socketServeur = new DatagramSocket(null);
- // // 2 - Réservation du port
- // InetSocketAddress adresse = new InetSocketAddress(
- // "localhost",
- // 6666
- // );
- // socketServeur.bind(adresse);
- // byte[] recues = new byte[1024]; // tampon d'émission
- // byte[] envoyees; // tampon de réception
- // // 3 - Recevoir
- // DatagramPacket paquetRecu = new DatagramPacket(
- // recues,
- // recues.length
- // );
- // socketServeur.receive(paquetRecu);
- // InetAddress adrClient = paquetRecu.getAddress();
- // int prtClient = paquetRecu.getPort();
- // System.out.println(
- // "Nouveau client : @" + adrClient + ":" + prtClient
- // );
- // // 4 - Émettre
- // String reponse = "Serveur RX302 ready";
- // envoyees = reponse.getBytes();
- // DatagramPacket paquetEnvoye = new DatagramPacket(
- // envoyees,
- // envoyees.length,
- // adrClient,
- // prtClient
- // );
- // socketServeur.send(paquetEnvoye);
- // // 5 - Libérer le canal
- // socketServeur.close();
- // } catch (Exception e) {
- // System.err.println(e);
- // }
- // }
-}
diff --git a/app/src/main/java/clientserver/client/Client.java b/app/src/main/java/clientserver/client/Client.java
new file mode 100644
index 0000000..05f65d2
--- /dev/null
+++ b/app/src/main/java/clientserver/client/Client.java
@@ -0,0 +1,89 @@
+package clientserver.client;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.util.concurrent.TimeUnit;
+
+public class Client {
+
+ InetAddress clientAddress;
+ int clientPort;
+
+ public void setPort(int port) {
+ this.clientPort = port;
+ }
+
+ public int getPort() {
+ return this.clientPort;
+ }
+
+ public InetAddress getAddress() {
+ return this.clientAddress;
+ }
+
+ public Client(InetAddress address, int port) {
+ this.clientAddress = address;
+ this.clientPort = port;
+ }
+
+ public static void main(String[] args) {
+ try {
+ // 1 - Création du canal avec un port libre
+ DatagramSocket socketClient = new DatagramSocket();
+ InetAddress serverAddress = InetAddress.getByName("localhost");
+ int serverPort = 6666;
+
+ // 2 - Envoyer un message au serveur
+ String message = "Connection request";
+ byte[] sendData = message.getBytes();
+ DatagramPacket sendPacket = new DatagramPacket(
+ sendData,
+ sendData.length,
+ serverAddress,
+ serverPort
+ );
+ socketClient.send(sendPacket);
+ System.out.println("New connection request sent");
+
+ // 3 - Recevoir
+ byte[] receivedData = new byte[1024]; // tampon de réception
+ DatagramPacket receivedPacket = new DatagramPacket(
+ receivedData,
+ receivedData.length
+ );
+ socketClient.receive(receivedPacket);
+ String reponse = new String(
+ receivedPacket.getData(),
+ 0,
+ receivedPacket.getLength()
+ );
+
+ if (reponse.startsWith("PORT:")) {
+ int newPort = Integer.parseInt(reponse.substring(5));
+
+ System.out.println("Connected on port:" + newPort);
+
+ // 4 - Communiquer sur le nouveau port
+ for (int i = 0; i < 20; i++) {
+ String messagePort = "Test";
+ byte[] envoyeesPort = messagePort.getBytes();
+ DatagramPacket paquetPort = new DatagramPacket(
+ envoyeesPort,
+ envoyeesPort.length,
+ serverAddress,
+ newPort
+ );
+ socketClient.send(paquetPort);
+ System.out.println("Test sent");
+ TimeUnit.SECONDS.sleep(1);
+ }
+ }
+
+ // 5 - Libérer le canal
+ socketClient.close();
+ } catch (Exception e) {
+ System.err.println(e);
+ }
+ }
+}
diff --git a/app/src/main/java/clientserver/MistralDirectAPI.java b/app/src/main/java/clientserver/common/MistralDirectAPI.java
similarity index 98%
rename from app/src/main/java/clientserver/MistralDirectAPI.java
rename to app/src/main/java/clientserver/common/MistralDirectAPI.java
index 25c1318..65bc0bc 100644
--- a/app/src/main/java/clientserver/MistralDirectAPI.java
+++ b/app/src/main/java/clientserver/common/MistralDirectAPI.java
@@ -1,4 +1,4 @@
-package clientserver;
+package clientserver.common;
import java.io.FileInputStream;
import java.io.IOException;
diff --git a/app/src/main/java/clientserver/server/ClientHandler.java b/app/src/main/java/clientserver/server/ClientHandler.java
new file mode 100644
index 0000000..7d959a1
--- /dev/null
+++ b/app/src/main/java/clientserver/server/ClientHandler.java
@@ -0,0 +1,74 @@
+package clientserver.server;
+
+import clientserver.client.Client;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+
+public class ClientHandler implements Runnable {
+
+ private final DatagramSocket socket;
+ private final Client client;
+ private boolean running = true;
+
+ public ClientHandler(DatagramSocket socket, Client client) {
+ this.socket = socket;
+ this.client = client;
+ }
+
+ public void stop() {
+ running = false;
+ if (socket != null && !socket.isClosed()) {
+ socket.close();
+ }
+ }
+
+ @Override
+ public void run() {
+ System.out.println(
+ "Started handler for client " +
+ client.getAddress() +
+ ":" +
+ client.getPort()
+ );
+
+ // try {
+ // socket.setSoTimeout(30000);
+ // } catch (Exception e) {
+ // System.err.println("Could not set socket timeout");
+ // }
+
+ while (running && !socket.isClosed()) {
+ DatagramPacket packet = Server.receivedPacket(socket);
+ if (packet == null) continue;
+
+ String message = new String(
+ packet.getData(),
+ 0,
+ packet.getLength()
+ );
+ System.out.println(
+ "Received from " +
+ client.getAddress() +
+ ":" +
+ client.getPort() +
+ ": " +
+ message
+ );
+ // Reply with echo
+ // String response = "ECHO: " + message;
+ // Server.sendMessage(
+ // socket,
+ // response,
+ // client.getAddress(),
+ // client.getPort()
+ // );
+ }
+
+ System.out.println(
+ "Client handler terminated for " +
+ client.getAddress() +
+ ":" +
+ client.getPort()
+ );
+ }
+}
diff --git a/app/src/main/java/clientserver/server/Server.java b/app/src/main/java/clientserver/server/Server.java
new file mode 100644
index 0000000..ef2f21d
--- /dev/null
+++ b/app/src/main/java/clientserver/server/Server.java
@@ -0,0 +1,140 @@
+package clientserver.server;
+
+import clientserver.client.Client;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+
+public class Server {
+
+ private int mainServerPort;
+ private DatagramSocket mainServerSocket;
+ private boolean isRunning;
+
+ public Server(int port) {
+ this.mainServerPort = port;
+ mainServerSocket = createSocket(this.mainServerPort);
+ isRunning = true;
+ }
+
+ private DatagramSocket createSocket(int port) {
+ try {
+ return new DatagramSocket(port);
+ } catch (Exception e) {
+ System.err.println("Failed to bind server socket on port " + port);
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private DatagramSocket createNewSocket() {
+ try {
+ return new DatagramSocket(); // Reserve a random port
+ } catch (Exception e) {
+ System.err.println("Failed to create new server socket");
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static DatagramPacket receivedPacket(DatagramSocket socket) {
+ byte[] receivedData = new byte[1024];
+ DatagramPacket receivedPacket = new DatagramPacket(
+ receivedData,
+ receivedData.length
+ );
+
+ try {
+ socket.receive(receivedPacket); // Blocking call
+ return receivedPacket;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static void sendMessage(
+ DatagramSocket socket,
+ String message,
+ java.net.InetAddress address,
+ int port
+ ) {
+ try {
+ byte[] sendData = message.getBytes();
+ DatagramPacket packetToSend = new DatagramPacket(
+ sendData,
+ sendData.length,
+ address,
+ port
+ );
+ socket.send(packetToSend);
+ } catch (IOException e) {
+ System.err.println(
+ "Failed to send message to " + address + ":" + port
+ );
+ e.printStackTrace();
+ }
+ }
+
+ private void handleNewConnection() {
+ DatagramPacket packet = receivedPacket(mainServerSocket);
+ if (packet == null) return;
+
+ Client client = new Client(packet.getAddress(), packet.getPort());
+
+ // Log the initial connection request
+ System.out.println(
+ "New connection request from " +
+ client.getAddress() +
+ ":" +
+ client.getPort()
+ );
+
+ // Process the received message
+ String message = new String(packet.getData(), 0, packet.getLength());
+ System.out.println(
+ "Received message from " +
+ client.getAddress() +
+ ":" +
+ client.getPort() +
+ ": " +
+ message
+ );
+
+ // Create a new socket for this client
+ DatagramSocket clientSocket = createNewSocket();
+ if (clientSocket == null) return;
+
+ int newPort = clientSocket.getLocalPort();
+ client.setPort(newPort);
+
+ // Send new port information to client
+ String response = "PORT:" + newPort;
+ sendMessage(
+ mainServerSocket,
+ response,
+ client.getAddress(),
+ packet.getPort()
+ );
+
+ // Create and start a ClientHandler for this connection
+ ClientHandler handler = new ClientHandler(clientSocket, client);
+ Thread thread = new Thread(handler);
+ thread.start();
+ }
+
+ public void run() {
+ System.out.println("Server started on port " + mainServerPort);
+ while (isRunning) {
+ try {
+ handleNewConnection();
+ } catch (Exception e) {
+ System.err.println(
+ "Error handling connection: " + e.getMessage()
+ );
+ e.printStackTrace();
+ }
+ }
+ System.out.println("Server shutdown");
+ }
+}