Compare commits

...

10 Commits

Author SHA1 Message Date
b35ab6e691 add cli interface instructions 2026-02-07 13:02:04 +01:00
f88cfe81dc fix import 2026-02-07 12:59:06 +01:00
ef4fdc1c9c reorganize ex6 2026-02-07 12:57:27 +01:00
a425be712e ex6 2026-02-07 12:53:08 +01:00
1492f078f9 debut debut 2026-02-04 11:16:49 +01:00
5c3e7fcdf5 debut 2026-02-04 10:38:14 +01:00
77df0f8298 ex5 2026-02-04 10:14:53 +01:00
22a11a0fa6 ex4 2026-02-04 10:07:41 +01:00
db77793f23 ex3 2026-02-04 09:25:01 +01:00
f5a11fc2de ex2 2026-02-04 09:24:56 +01:00
28 changed files with 1268 additions and 2 deletions

View File

@@ -4,8 +4,6 @@ import java.io.IOException;
import java.net.DatagramPacket; import java.net.DatagramPacket;
import java.net.DatagramSocket; import java.net.DatagramSocket;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Random;
import java.util.Scanner;
public class Client { public class Client {

10
src/Ex2/App.java Normal file
View File

@@ -0,0 +1,10 @@
package Ex2;
import java.net.InetSocketAddress;
public class App {
public static void main(String[] args) throws Exception {
Server server = new Server(6666);
Client client = new Client(new InetSocketAddress("localhost", 6666));
}
}

77
src/Ex2/Client.java Normal file
View File

@@ -0,0 +1,77 @@
package Ex2;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.temporal.TemporalUnit;
public class Client {
private final DatagramSocket socket;
private final InetSocketAddress address;
/**
* Create a new client
*
* @param address server adress (needed
* @throws IOException
*/
public Client(InetSocketAddress address) throws IOException {
this.address = address;
this.socket = new DatagramSocket();
sendGreetings();
readMessage();
this.socket.close();
}
private void sendGreetings() throws IOException {
sendMessage(Instant.now().toString());
}
public void sendMessage(String message) throws IOException {
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, this.address.getAddress(),
this.address.getPort());
this.socket.send(packet);
}
private void processMessage(DatagramPacket packet) {
String message = new String(packet.getData(), 0, packet.getLength());
long t2 = Instant.now().toEpochMilli();
System.out.println("[Client] Message recieved : " + message);
String[] times = message.split(" ");
long t1 = Instant.parse(times[0]).toEpochMilli();
long tPrime1 = Instant.parse(times[1]).toEpochMilli();
long tPrime2 = Instant.parse(times[2]).toEpochMilli();
var delta = (t2 - t1) - (tPrime2 - tPrime1);
var theta = (tPrime1 + tPrime2) / 2 - (t1 + t2) / 2;
var now = System.currentTimeMillis();
System.out.println("Delta : " + delta + "ms, Theta : " + theta + "ms");
System.out.println("Temps actuel : " + new Timestamp(now));
System.out.println("Temps corrigé: " + new Timestamp(now + theta));
}
private boolean readMessage() {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
try {
this.socket.receive(packet);
processMessage(packet);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
private void readMessages() {
while (true) {
if(!readMessage())
break;
}
}
}

52
src/Ex2/Server.java Normal file
View File

@@ -0,0 +1,52 @@
package Ex2;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.time.Instant;
public class Server {
private final DatagramSocket socket;
public Server(int port) throws SocketException {
this.socket = new DatagramSocket(port);
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);
this.socket.send(packet);
}
private void processMessage(DatagramPacket packet) throws IOException {
Instant tPrime1 = Instant.now();
String message = new String(packet.getData(), 0, packet.getLength());
System.out.println("[Server] Message recieved : " + message);
Instant t1 = Instant.parse(message);
Instant tPrime2 = Instant.now();
sendMessage(t1.toString() + " " + tPrime1.toString() + " " + tPrime2.toString(), packet.getAddress(), packet.getPort());
}
private void readMessages() {
while (true) {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
try {
this.socket.receive(packet);
processMessage(packet);
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
}

11
src/Ex3/App.java Normal file
View File

@@ -0,0 +1,11 @@
package Ex3;
import java.net.InetSocketAddress;
public class App {
public static void main(String[] args) throws Exception {
Server server = new Server(6666);
Client client = new Client(new InetSocketAddress("localhost", 6666));
// Client client2 = new Client(new InetSocketAddress("localhost", 6666));
}
}

34
src/Ex3/Client.java Normal file
View File

@@ -0,0 +1,34 @@
package Ex3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
public class Client {
private final Socket socket;
/**
* Create a new client
*
* @param address server adress (needed
* @throws IOException
*/
public Client(InetSocketAddress address) throws IOException {
this.socket = new Socket(address.getAddress(), address.getPort());
readMessage();
this.socket.close();
}
private void readMessage() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
System.out.println("Heure du serveur : " + reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}

45
src/Ex3/Server.java Normal file
View File

@@ -0,0 +1,45 @@
package Ex3;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.time.Instant;
public class Server {
private final ServerSocket serverSocket;
public Server(int port) throws IOException {
this.serverSocket = new ServerSocket(port);
new Thread(this::listen).start();
}
public int getPort() {
return this.serverSocket.getLocalPort();
}
private void processConnexion(Socket socket) throws IOException {
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
writer.println(Instant.now().toString());
socket.close();
}
private void listen() {
while (true) {
try {
Socket connexion = this.serverSocket.accept();
processConnexion(connexion);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

17
src/Ex4/App.java Normal file
View File

@@ -0,0 +1,17 @@
package Ex4;
import java.net.InetSocketAddress;
public class App {
public static void main(String[] args) throws Exception {
Server server = new Server(6666);
Client client = new Client(new InetSocketAddress("localhost", 6666));
client.sendMessage("DATE");
client.sendMessage("HOUR");
client.sendMessage("FULL");
client.sendMessage("CLOSE");
// stopping server
server.close();
}
}

45
src/Ex4/Client.java Normal file
View File

@@ -0,0 +1,45 @@
package Ex4;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
public class Client {
private final Socket socket;
/**
* Create a new client
*
* @param address server adress (needed
* @throws IOException
*/
public Client(InetSocketAddress address) throws IOException {
this.socket = new Socket(address.getAddress(), address.getPort());
}
public void sendMessage(String message) {
PrintWriter writer;
try {
writer = new PrintWriter(this.socket.getOutputStream(), true);
writer.println(message);
} catch (IOException e) {
e.printStackTrace();
}
readMessage();
}
private void readMessage() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
System.out.println("[Client] " + reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}

102
src/Ex4/Server.java Normal file
View File

@@ -0,0 +1,102 @@
package Ex4;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.time.Instant;
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class Server {
private final ServerSocket serverSocket;
public Server(int port) throws IOException {
this.serverSocket = new ServerSocket(port);
new Thread(this::listen).start();
System.out.println("Server running on port " + getPort());
}
public void close() {
try {
this.serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public int getPort() {
return this.serverSocket.getLocalPort();
}
private void processConnexion(Socket socket) throws IOException {
new Thread(new Runnable() {
@Override
public void run() {
try {
readMessages(socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
private void listen() {
try {
while (true) {
Socket connexion = this.serverSocket.accept();
processConnexion(connexion);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void readMessages(Socket socket) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
boolean done = false;
while (!done) {
String message = reader.readLine();
Date date = Date.from(Instant.now());
Calendar now = GregorianCalendar.getInstance();
now.setTime(date);
System.out.println("[Server] Received " + message);
switch (message) {
case "DATE":
writer.println(LocalDate.now());
break;
case "HOUR":
writer.println(now.get(Calendar.HOUR_OF_DAY) + ":" + now.get(Calendar.MINUTE));
break;
case "FULL":
writer.println(Instant.now().toString());
break;
case "CLOSE":
System.out.println("[Server] Closing socket...");
socket.close();
done = true;
break;
default:
break;
}
}
}
}

22
src/Ex5/App.java Normal file
View File

@@ -0,0 +1,22 @@
package Ex5;
import java.net.InetSocketAddress;
import java.util.Scanner;
public class App {
public static void main(String[] args) throws Exception {
Server server = new Server(6666);
Client client = new Client(new InetSocketAddress("localhost", 6666));
Scanner scanner = new Scanner(System.in);
System.out.println("Entrez des messages :");
while (true) {
String line = scanner.nextLine();
System.out.println("[Client -> Server] " + line);
client.sendMessage(line);
String response = client.readMessage();
System.out.println("[Client <- Server] " + response);
}
}
}

45
src/Ex5/Client.java Normal file
View File

@@ -0,0 +1,45 @@
package Ex5;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
public class Client {
private final Socket socket;
/**
* Create a new client
*
* @param address server adress (needed
* @throws IOException
*/
public Client(InetSocketAddress address) throws IOException {
this.socket = new Socket(address.getAddress(), address.getPort());
}
public void sendMessage(String message) {
PrintWriter writer;
try {
writer = new PrintWriter(this.socket.getOutputStream(), true);
writer.println(message);
} catch (IOException e) {
e.printStackTrace();
}
}
public String readMessage() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
return reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

65
src/Ex5/Server.java Normal file
View File

@@ -0,0 +1,65 @@
package Ex5;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private final ServerSocket serverSocket;
public Server(int port) throws IOException {
this.serverSocket = new ServerSocket(port);
new Thread(this::listen).start();
System.out.println("Server running on port " + getPort());
}
public void close() {
try {
this.serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public int getPort() {
return this.serverSocket.getLocalPort();
}
private void processConnexion(Socket socket) throws IOException {
new Thread(new Runnable() {
@Override
public void run() {
try {
readMessages(socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
private void listen() {
try {
while (true) {
Socket connexion = this.serverSocket.accept();
processConnexion(connexion);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void readMessages(Socket socket) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
while (true) {
String message = reader.readLine();
writer.println(message.toUpperCase());
}
}
}

23
src/Ex6/README.md Normal file
View File

@@ -0,0 +1,23 @@
# Architecture
- The main package contains the logic.
- The network package contains the protocol implementation details.
# Running the program
## Launch server
Run Serveur.java
## Launch Client
Run Client.java
## Launch Server + Client
Run App.java
# CLI interface
To play a move, enter the number of the cell you want to change.
To exit, type "stop" or "close".

20
src/Ex6/main/App.java Normal file
View File

@@ -0,0 +1,20 @@
package Ex6.main;
import java.io.IOException;
import java.net.Socket;
public class App {
/**
* Run this to launch the server and immediatly connect to it with a CLI Client.
*/
public static void main(String[] args) throws IOException {
final int port = 6666;
System.out.println("Launching server ...");
Serveur serveur = new Serveur(port);
System.out.println("Connecting client1 ...");
Client client1 = new Client(new Socket("localhost", port));
}
}

160
src/Ex6/main/Client.java Normal file
View File

@@ -0,0 +1,160 @@
package Ex6.main;
import java.io.IOException;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner;
import Ex6.main.Jeu.EtatCase;
import Ex6.network.Connexion;
import Ex6.network.packets.EndGamePacket;
import Ex6.network.packets.InvalidMovePacket;
import Ex6.network.packets.LeavePacket;
import Ex6.network.packets.NewGamePacket;
import Ex6.network.packets.PlayMovePacket;
import Ex6.network.packets.PlayerMovePacket;
public class Client extends Connexion {
private EtatCase player = EtatCase.Vide;
private EtatCase turn = EtatCase.Vide;
private EtatCase[] cases = new EtatCase[9];
// I swear I typed those by hand
private static final String[] CELL_EMOJIS = {
"0", "1", "2",
"3", "4", "5",
"6", "7", "8",
};
/**
* Run this to connect to an existing server
*/
public static void main(String[] args) throws IOException {
new Client(new Socket("localhost", 6666));
}
public Client(Socket socket) throws IOException {
super(socket);
Scanner scanner = new Scanner(System.in);
boolean done = false;
while (!done) {
String line = scanner.nextLine();
switch (line) {
case "CLOSE":
case "close":
case "STOP":
case "stop":
sendPacket(new LeavePacket());
socket.close();
done = true;
break;
default:
break;
}
try {
int cellIndex = Integer.parseInt(line);
if (cellIndex > 8 || cellIndex < 0) {
System.out.println("Number not in range !");
continue;
}
sendPacket(new PlayMovePacket(cellIndex));
} catch (NumberFormatException e) {
System.out.println("Number not recognized !");
}
}
scanner.close();
System.out.println("Bye !");
}
private boolean isPlayerTurn() {
return this.player == this.turn;
}
private String getPlayerCharacter() {
return this.player == EtatCase.Rond ? "" : "";
}
private void switchTurn() {
if (this.turn == EtatCase.Croix) {
this.turn = EtatCase.Rond;
} else {
this.turn = EtatCase.Croix;
}
}
private String renderBoard() {
String board = "";
for (int i = 0; i < 9; i++) {
EtatCase cell = cases[i];
switch (cell) {
case Vide:
board += CELL_EMOJIS[i];
break;
case Croix:
board += "";
break;
case Rond:
board += "";
break;
}
if (i % 3 == 2)
board += "\n";
}
return board;
}
private void printBoard() {
System.out.println("\n\n\n\n\n\n\n\n\n");
System.out.println(renderBoard());
if (isPlayerTurn()) {
System.out.println("C'est à votre tour !");
} else {
System.out.println("En attente de l'adversaire ...");
}
}
@Override
public void visit(EndGamePacket packet) {
System.out.println("Jeu terminé !");
printBoard();
System.out.println("\n\n\nVous avez " + (packet.getVainqueur() == player ? "gagné 🤩" : "perdu 💩"));
}
@Override
public void visit(InvalidMovePacket packet) {
System.out.println("Coups non autorisé !");
}
@Override
public void visit(NewGamePacket packet) {
this.player = packet.isRond() ? EtatCase.Rond : EtatCase.Croix;
this.turn = EtatCase.Croix;
Arrays.fill(cases, EtatCase.Vide);
System.out.printf("Nouvelle partie !\n", this.getPlayerCharacter());
System.out.println("Vous êtes les " + getPlayerCharacter());
printBoard();
}
@Override
public void visit(PlayerMovePacket packet) {
cases[packet.getCellIndex()] = turn;
switchTurn();
printBoard();
}
@Override
public void visit(LeavePacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visit'");
}
@Override
public void visit(PlayMovePacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visit'");
}
}

115
src/Ex6/main/Jeu.java Normal file
View File

@@ -0,0 +1,115 @@
package Ex6.main;
import java.util.Arrays;
import java.util.Random;
public class Jeu {
public enum EtatCase {
Croix,
Rond,
Vide
}
private boolean gameDone;
private EtatCase turn = EtatCase.Vide;
private EtatCase[] cases = new EtatCase[9];
private final Serveur serveur;
private static final int[][] CHECK_INDICES = {
// rows
{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
// columns
{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
// diagonals
{0, 4, 8}, {2, 4, 6}
};
public Jeu(Serveur serveur) {
this.serveur = serveur;
}
/**
* Start a new game and randomly assign symbols to players
*/
public void start() {
boolean player1Rond = new Random().nextBoolean();
this.serveur.joueur1.startGame(player1Rond);
this.serveur.joueur2.startGame(!player1Rond);
this.gameDone = false;
this.turn = EtatCase.Croix;
Arrays.fill(cases, EtatCase.Vide);
}
private void switchTurn() {
if (this.turn == EtatCase.Croix){
this.turn = EtatCase.Rond;
} else {
this.turn = EtatCase.Croix;
}
}
/**
* Check for winning pattern by looking at an index table.
* @return EtatCase.Vide if no one won.
*/
private EtatCase checkWin() {
for (int i = 0; i < CHECK_INDICES.length; i++) {
EtatCase previousCell = null;
boolean skip = false;
for (int j = 0; j < 3; j++) {
int cellIndex = CHECK_INDICES[i][j];
EtatCase cell = cases[cellIndex];
if (cell == EtatCase.Vide) {
skip = true;
break;
}
if (previousCell != null) {
if (previousCell != cell) {
skip = true;
break;
}
}
previousCell = cell;
}
if (skip)
continue;
return previousCell;
}
return EtatCase.Vide;
}
/**
* Apply a move for the current player.
* Be aware that the move is not checked and should be done before.
* @see Ex6.main.Jeu.checkWin
* @param cellIndex index of the cell to replace.
* @return EtatCase.Vide if no one won.
*/
public EtatCase playMove(int cellIndex) {
cases[cellIndex] = this.turn;
switchTurn();
EtatCase winner = checkWin();
if (winner != EtatCase.Vide)
this.gameDone = true;
return winner;
}
public EtatCase getCell(int index) {
return cases[index];
}
public EtatCase getTurn() {
return turn;
}
public boolean isGameDone() {
return this.gameDone;
}
}

90
src/Ex6/main/Joueur.java Normal file
View File

@@ -0,0 +1,90 @@
package Ex6.main;
import java.io.IOException;
import java.net.Socket;
import Ex6.main.Jeu.EtatCase;
import Ex6.network.Connexion;
import Ex6.network.packets.EndGamePacket;
import Ex6.network.packets.InvalidMovePacket;
import Ex6.network.packets.LeavePacket;
import Ex6.network.packets.NewGamePacket;
import Ex6.network.packets.PlayMovePacket;
import Ex6.network.packets.PlayerMovePacket;
public class Joueur extends Connexion {
private final Jeu jeu;
private final Serveur serveur;
private EtatCase player;
public Joueur(Socket socket, Jeu jeu, Serveur serveur) throws IOException {
super(socket);
this.jeu = jeu;
this.serveur = serveur;
}
/**
* Notify a new game has started to the client
* @param rond True if player is 'O'
*/
public void startGame(boolean rond) {
this.player = rond ? EtatCase.Rond : EtatCase.Croix;
sendPacket(new NewGamePacket(rond));
}
@Override
public void visit(LeavePacket packet) {
close();
}
@Override
public void visit(PlayMovePacket packet) {
// player should not play
if (this.jeu.isGameDone() || this.jeu.getTurn() != this.player) {
sendPacket(new InvalidMovePacket());
return;
}
// check placing on empty cell
if (this.jeu.getCell(packet.getCellIndex()) != EtatCase.Vide) {
sendPacket(new InvalidMovePacket());
return;
}
EtatCase winner = this.jeu.playMove(packet.getCellIndex());
this.serveur.broadcastPacket(new PlayerMovePacket(packet.getCellIndex()));
if (winner != EtatCase.Vide) {
this.serveur.broadcastPacket(new EndGamePacket(winner));
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// automatically launch new game after 10s
this.jeu.start();
}
}
@Override
public void visit(EndGamePacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visit'");
}
@Override
public void visit(InvalidMovePacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visit'");
}
@Override
public void visit(NewGamePacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visit'");
}
@Override
public void visit(PlayerMovePacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visit'");
}
}

69
src/Ex6/main/Serveur.java Normal file
View File

@@ -0,0 +1,69 @@
package Ex6.main;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import Ex6.network.Packet;
public class Serveur {
private final Jeu jeu;
private final ServerSocket serverSocket;
public Joueur joueur1;
public Joueur joueur2;
/**
* @brief Run this to launch the server in headless mode
*/
public static void main(String[] args) throws IOException {
new Serveur(6666);
}
/**
* Start a TicTacToe server on the specified port
* @param port the port to listen to
* @throws IOException
*/
public Serveur(int port) throws IOException {
this.jeu = new Jeu(this);
this.serverSocket = new ServerSocket(port);
this.joueur1 = null;
this.joueur2 = null;
new Thread(this::acceptLoop).start();
}
/**
* Send a packet to both players
* @param packet the packet to send
*/
public void broadcastPacket(Packet packet) {
this.joueur1.sendPacket(packet);
this.joueur2.sendPacket(packet);
}
/**
* Here we accept only the first two players.
* If a player leaves, the server needs to be restarted.
* It's not robust but enough for a demo.
*/
private void acceptLoop() {
while (true) {
try {
Socket socket = this.serverSocket.accept();
if (this.joueur1 == null) {
this.joueur1 = new Joueur(socket, jeu, this);
continue;
}
if (this.joueur2 == null) {
this.joueur2 = new Joueur(socket, jeu, this);
this.jeu.start();
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,81 @@
package Ex6.network;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
/**
* Abstraction of TCP connection implementing PacketVisitor
*/
public abstract class Connexion implements PacketVisitor {
private final Socket socket;
private final ObjectOutputStream out;
private ObjectInputStream in;
public Connexion(Socket socket) throws IOException {
this.socket = socket;
this.out = new ObjectOutputStream(this.socket.getOutputStream());
new Thread(this::readPackets).start();
}
/**
* Send a packet through network
* @param packet The packet to send
*/
public void sendPacket(Packet packet) {
try {
out.writeObject(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Loop to process new packets infinitely.
*/
private void readPackets() {
try {
this.in = new ObjectInputStream(this.socket.getInputStream());
while (true) {
try {
processPacket();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Read a packet.
* @return The packet read.
*/
private Packet readPacket() throws ClassNotFoundException, IOException {
Object o = in.readObject();
Packet packet = (Packet) o;
return packet;
}
/**
* Processing the packet through double-dispatch.
*/
public void processPacket() throws ClassNotFoundException, IOException {
Packet packet = readPacket();
visit(packet);
}
/**
* Close the connection.
*/
protected void close() {
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,8 @@
package Ex6.network;
/**
* Abstract class representing a packet (implementing the Visitor design pattern)
*/
public abstract class Packet {
public abstract void accept(PacketVisitor visitor);
}

View File

@@ -0,0 +1,29 @@
package Ex6.network;
import Ex6.network.packets.EndGamePacket;
import Ex6.network.packets.InvalidMovePacket;
import Ex6.network.packets.LeavePacket;
import Ex6.network.packets.NewGamePacket;
import Ex6.network.packets.PlayMovePacket;
import Ex6.network.packets.PlayerMovePacket;
public interface PacketVisitor {
void visit(EndGamePacket packet);
void visit(InvalidMovePacket packet);
void visit(LeavePacket packet);
void visit(NewGamePacket packet);
void visit(PlayerMovePacket packet);
void visit(PlayMovePacket packet);
/**
* Double-dispatch
*/
default void visit(Packet packet) {
packet.accept(this);
}
}

View File

@@ -0,0 +1,29 @@
package Ex6.network.packets;
import java.io.Serializable;
import Ex6.main.Jeu.EtatCase;
import Ex6.network.Packet;
import Ex6.network.PacketVisitor;
/**
* Packet sent to both clients to end a game (providing the winner)
*/
public class EndGamePacket extends Packet implements Serializable{
private final EtatCase vainqueur;
public EndGamePacket(EtatCase vainqueur) {
this.vainqueur = vainqueur;
}
@Override
public void accept(PacketVisitor visitor) {
visitor.visit(this);
}
public EtatCase getVainqueur() {
return vainqueur;
}
}

View File

@@ -0,0 +1,18 @@
package Ex6.network.packets;
import java.io.Serializable;
import Ex6.network.Packet;
import Ex6.network.PacketVisitor;
/**
* Packet send to a client to indicate an invalid move.
*/
public class InvalidMovePacket extends Packet implements Serializable {
@Override
public void accept(PacketVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -0,0 +1,18 @@
package Ex6.network.packets;
import java.io.Serializable;
import Ex6.network.Packet;
import Ex6.network.PacketVisitor;
/**
* Packet sent by a client to indicate he is leaving.
*/
public class LeavePacket extends Packet implements Serializable {
@Override
public void accept(PacketVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -0,0 +1,28 @@
package Ex6.network.packets;
import java.io.Serializable;
import Ex6.network.Packet;
import Ex6.network.PacketVisitor;
/**
* Packet sent to both client to indicate a new game has started (providing the symbol of the player for this game).
*/
public class NewGamePacket extends Packet implements Serializable {
private final boolean rond;
public NewGamePacket(boolean rond) {
this.rond = rond;
}
@Override
public void accept(PacketVisitor visitor) {
visitor.visit(this);
}
public boolean isRond() {
return rond;
}
}

View File

@@ -0,0 +1,27 @@
package Ex6.network.packets;
import java.io.Serializable;
import Ex6.network.Packet;
import Ex6.network.PacketVisitor;
/**
* Packet sent by a client to draw a symbol in a cell.
*/
public class PlayMovePacket extends Packet implements Serializable{
private final int cellIndex;
public PlayMovePacket(int cellIndex) {
this.cellIndex = cellIndex;
}
@Override
public void accept(PacketVisitor visitor) {
visitor.visit(this);
}
public int getCellIndex() {
return cellIndex;
}
}

View File

@@ -0,0 +1,28 @@
package Ex6.network.packets;
import java.io.Serializable;
import Ex6.network.Packet;
import Ex6.network.PacketVisitor;
/**
* Packet sent to both client to confirm a move and switch turns.
*/
public class PlayerMovePacket extends Packet implements Serializable {
private final int cellIndex;
public PlayerMovePacket(int cellIndex) {
this.cellIndex = cellIndex;
}
@Override
public void accept(PacketVisitor visitor) {
visitor.visit(this);
}
public int getCellIndex() {
return cellIndex;
}
}