Fix: major changes to TCP server/client stack.

This commit is contained in:
2026-04-26 16:16:05 +02:00
parent 5e958dded4
commit 1f44e415e4
3 changed files with 68 additions and 97 deletions
@@ -8,11 +8,10 @@ import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
public class TCPClient implements Serializable{ public class TCPClient {
Socket communicationSocket = null; Socket communicationSocket;
ObjectInputStream socketReceive; ObjectInputStream socketReceive;
ObjectOutputStream socketSend; ObjectOutputStream socketSend;
GameController controller; GameController controller;
String hostname; String hostname;
int port; int port;
@@ -23,43 +22,44 @@ public class TCPClient implements Serializable{
this.port = port; this.port = port;
} }
public boolean start(String user, int players){ public boolean start(String user, int proposedNPlayers){
try{ try{
communicationSocket = new Socket(hostname, port); communicationSocket = new Socket(hostname, port);
socketSend = new ObjectOutputStream(communicationSocket.getOutputStream()); socketSend = new ObjectOutputStream(communicationSocket.getOutputStream());
socketReceive = new ObjectInputStream(communicationSocket.getInputStream()); socketReceive = new ObjectInputStream(communicationSocket.getInputStream());
socketSend.writeObject(new AddPlayer(user, players)); sendEvent(new AddPlayer(user, proposedNPlayers));
if(communicationSocket.getInputStream().read() == -1){ if(communicationSocket.getInputStream().read() == -1){
System.out.println("Could not connect to server");
return false; return false;
} }
else{ else{
Thread listener = new Thread(() -> ReceiveMessage()); Thread listener = new Thread(() -> receiveMessage());
listener.start(); listener.start();
return true; return true;
} }
} } catch (IOException e) {
catch(Exception e){ e.printStackTrace();
return false; return false;
} }
} }
private void ReceiveMessage(){ private void receiveMessage(){
while(true){ while(true){
try{ try{
Object read = socketReceive.readObject(); Object read = socketReceive.readObject();
if (read instanceof NetworkEvent) { //TODO non fare con instanceof if (read instanceof NetworkEvent event) { //TODO non fare con instanceof
NetworkEvent event = (NetworkEvent) read;
if(event.getIsError()) { if(event.getIsError()) {
System.out.println(event.toString()); System.out.println(event);
} else { } else {
event.apply(controller); event.apply(controller);
//clientController.view.update(); TODO //clientController.view.update(); TODO
} }
} }
else if (read instanceof Game) { else if (read instanceof Game model) {
controller.setModel((Game) read); controller.setModel(model);
} }
} }
@@ -69,11 +69,10 @@ public class TCPClient implements Serializable{
catch(ClassNotFoundException e){ catch(ClassNotFoundException e){
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return;
} }
} }
private void SendEvent(NetworkEvent event){ private void sendEvent(NetworkEvent event){
try{ try{
socketSend.writeObject(event); socketSend.writeObject(event);
} }
@@ -1,9 +1,7 @@
package it.polimi.ingsw.gc14.Network.TCP.Server; package it.polimi.ingsw.gc14.Network.TCP.Server;
import it.polimi.ingsw.gc14.Controller.GameController;
import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Model.Game;
import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.Network.EventType;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
@@ -12,12 +10,10 @@ import java.util.concurrent.BlockingQueue;
public class ClientHandler implements Runnable { public class ClientHandler implements Runnable {
private Socket clientSocket; private Socket clientSocket;
private TCPServer server; public ObjectInputStream in;
public ObjectInputStream in = null; public ObjectOutputStream out;
public ObjectOutputStream out = null;
List<ClientHandler> clientHandlers; List<ClientHandler> clientHandlers;
BlockingQueue<NetworkEvent> actionQueue; BlockingQueue<NetworkEvent> actionQueue;
private EventType eventType;
public Socket getClientSocket() { public Socket getClientSocket() {
return clientSocket; return clientSocket;
@@ -31,33 +27,24 @@ public class ClientHandler implements Runnable {
@Override @Override
public void run(){ public void run(){
clientLoop();
}
private void clientLoop(){
try{ try{
NetworkEvent input = null; in = new ObjectInputStream(clientSocket.getInputStream());
synchronized(in){ out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
}
while(true){ while(true){
try{ NetworkEvent event = (NetworkEvent) in.readObject();
input = (NetworkEvent) (in.readObject()); if(!actionQueue.add(event)){
if(!actionQueue.add(input)){ System.out.println("Error inserting action into queue");
System.out.println("An error occurred in inserting an action into queue");
}
}
catch(java.io.IOException e){
e.printStackTrace();
}
catch (ClassNotFoundException e){
throw new RuntimeException(e);
} }
} }
} }
catch (IOException e) { catch(IOException e){
clientHandlers.remove(this);
e.printStackTrace(); e.printStackTrace();
} }
catch(ClassNotFoundException e){
throw new RuntimeException(e);
}
} }
public void notifyEvent(NetworkEvent event){ public void notifyEvent(NetworkEvent event){
@@ -3,6 +3,7 @@ package it.polimi.ingsw.gc14.Network.TCP.Server;
import it.polimi.ingsw.gc14.Controller.GameController; import it.polimi.ingsw.gc14.Controller.GameController;
import it.polimi.ingsw.gc14.LimitedList; import it.polimi.ingsw.gc14.LimitedList;
import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Model.Game;
import it.polimi.ingsw.gc14.Network.EventType;
import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer;
@@ -14,32 +15,29 @@ import java.util.concurrent.BlockingQueue;
public class TCPServer { public class TCPServer {
int port = -1; int port;
int ConnectedPlayers = 0; int ConnectedPlayers;
ServerSocket serverTCP = null; ServerSocket serverTCP;
GameController gameController; GameController controller;
BlockingQueue<NetworkEvent> actionQueue; BlockingQueue<NetworkEvent> actionQueue;
private LimitedList<String> playerList; private LimitedList<String> playerList;
private List<ClientHandler> clientHandlers; private List<ClientHandler> clientHandlers;
private int getConnectedPlayers(){ private int getConnectedPlayers(){
return ConnectedPlayers; return ConnectedPlayers;
} }
public void start(){ public void start(){
clientHandlers = new ArrayList<>();
try{ try{
serverTCP = new ServerSocket(port); serverTCP = new ServerSocket(port);
} }
catch (IOException e){ catch (IOException e){
System.out.println("Could not listen on port: " + port); System.out.println("Could not start the server TCP on port: " + port);
e.printStackTrace(); e.printStackTrace();
return; return;
} }
System.out.println("Listening on port: " + port); System.out.println("Server TCP started on port: " + port);
while(true){ while(true){
Socket clientSocket = null; Socket clientSocket = null;
@@ -49,34 +47,42 @@ public class TCPServer {
ObjectInputStream clientSocketObj = new ObjectInputStream(clientSocket.getInputStream()); ObjectInputStream clientSocketObj = new ObjectInputStream(clientSocket.getInputStream());
NetworkEvent event = (NetworkEvent) clientSocketObj.readObject(); NetworkEvent event = (NetworkEvent) clientSocketObj.readObject();
synchronized (gameController){ if(!(event.getEventType() == EventType.ADD_PLAYER)){
if(!(event instanceof AddPlayer) || (gameController.getModel() != null && gameController.getModel().getCurrentPlayerNumber() >= gameController.getModel().getNPlayers())){ clientSocket.getOutputStream().write((int)(-1));
clientSocket.getOutputStream().write((int)(-1)); clientSocket.close();
System.out.println("Invalid parameters. Connection terminated.\n");
}
else{
AddPlayer eventAddPlayer = (AddPlayer) event;
if (eventAddPlayer.getProposedNPlayer() < 2 || eventAddPlayer.getProposedNPlayer() > 5) {
clientSocket.getOutputStream().write((int) (-1));
clientSocket.close(); clientSocket.close();
System.out.println("Invalid parameters. Connection terminated.\n"); System.out.println("Invalid parameters. Connection terminated.\n");
} }
else{ synchronized (controller) {
synchronized (gameController) { if (playerList.isEmpty()){
AddPlayer addPlayer = (AddPlayer) event; Game model = new Game(eventAddPlayer.getProposedNPlayer());
if(playerList.isEmpty() && (addPlayer.getProposedNPlayer() < 2 || addPlayer.getProposedNPlayer() > 5)){ controller.setModel(model);
clientSocket.getOutputStream().write((int)(-1)); playerList.setLimit(eventAddPlayer.getProposedNPlayer());
clientSocket.close();
System.out.println("Invalid parameters. Connection terminated.\n");
}
else if(gameController.addPlayer(addPlayer.getUsername())){
if(playerList.isEmpty()){
Game game = new Game(addPlayer.getProposedNPlayer());
gameController.setModel(game);
playerList.setLimit(addPlayer.getProposedNPlayer());
}
playerList.add(addPlayer.getUsername());
clientSocket.getOutputStream().write((int)(1));
}
} }
if (controller.addPlayer(eventAddPlayer.getUsername())) {
playerList.add(eventAddPlayer.getUsername());
clientSocket.getOutputStream().write((int) (1));
System.out.println("Accepted player: " + eventAddPlayer.getUsername());
ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, actionQueue);
clientHandlers.add(clientHandler);
ConnectedPlayers++;
Thread t = new Thread(clientHandler);
t.start();
} else {
clientSocket.getOutputStream().write((int) (-1));
clientSocket.close();
System.out.println("Player could not be added. Connection terminated.\n");
}
} }
} }
// gestione di ADD_PLAYER
} }
catch(IOException e){ catch(IOException e){
e.printStackTrace(); e.printStackTrace();
@@ -84,38 +90,17 @@ public class TCPServer {
catch(ClassNotFoundException e){ catch(ClassNotFoundException e){
throw new RuntimeException(e); throw new RuntimeException(e);
} }
System.out.println("Accepted player: " + gameController.getModel().getPlayerByUsername(clientSocket.getInetAddress().toString()));
ConnectedPlayers++;
ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, actionQueue);
clientHandlers.add(clientHandler);
//Sending model to clients
if(ConnectedPlayers == gameController.getModel().getNPlayers()){
for (ClientHandler handler : clientHandlers) {
try {
synchronized(handler.out){
ObjectOutputStream socketTx = new ObjectOutputStream(handler.getClientSocket().getOutputStream());
socketTx.writeObject(gameController.getModel());
}
}
catch(IOException e){
e.printStackTrace();
}
}
}
Thread t = new Thread(clientHandler);
t.start();
} }
} }
public TCPServer(GameController gameController, int port, BlockingQueue<NetworkEvent> actionQueue, LimitedList<String> players){ public TCPServer(GameController gameController, int port, BlockingQueue<NetworkEvent> actionQueue, LimitedList<String> players){
this.port = port; this.port = port;
this.gameController = gameController; this.ConnectedPlayers = 0;
this.serverTCP = null;
this.controller = gameController;
this.actionQueue = actionQueue; this.actionQueue = actionQueue;
this.playerList = players; this.playerList = players;
this.clientHandlers = new ArrayList<>();
} }
public void notifyAll(NetworkEvent event){ public void notifyAll(NetworkEvent event){