added better network support and disconnecting doesnt clos the client who hosts the server now

This commit is contained in:
Hanno Fleischer
2024-12-11 19:10:46 +01:00
parent f09766eb42
commit f9772732c4
9 changed files with 83 additions and 47 deletions

View File

@@ -339,7 +339,10 @@ public void afterGameCleanup() {
MainView main = (MainView) mainView; MainView main = (MainView) mainView;
main.getJoinDialog().disconnect(); main.getJoinDialog().disconnect();
main.getHostDialog().shutdownServer(); System.out.println("Disconnecting from server..." + clientGameLogic.isHost());
if (clientGameLogic.isHost()) {
main.getHostDialog().shutdownServer();
}
ceremonyView.afterGameCleanup(); ceremonyView.afterGameCleanup();
} }

View File

@@ -98,27 +98,16 @@ protected void startServer() {
*/ */
public void shutdownServer() { public void shutdownServer() {
serverInstance.shutdown();
// Wait for the server to shut down
try { try {
Thread.sleep(1000); serverThread.join(); // Wait for the server thread to finish
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
System.err.println("Thread was interrupted: " + e.getMessage());
} }
if (serverInstance != null) { System.out.println("Server shutdown successfully.");
serverInstance.shutdown();
serverInstance = null;
}
if (serverThread != null && serverThread.isAlive()) {
serverThread.interrupt();
try {
serverThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
serverThread = null;
}
} }
/** /**

View File

@@ -15,6 +15,9 @@
import java.io.IOException; import java.io.IOException;
import java.lang.System.Logger; import java.lang.System.Logger;
import java.lang.System.Logger.Level; import java.lang.System.Logger.Level;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@@ -31,6 +34,7 @@ public class MdgaServer implements MessageListener<HostedConnection>, Connection
private static int port; private static int port;
private final ServerGameLogic logic; private final ServerGameLogic logic;
private final BlockingQueue<ReceivedMessage> pendingMessages = new LinkedBlockingQueue<>(); private final BlockingQueue<ReceivedMessage> pendingMessages = new LinkedBlockingQueue<>();
private volatile boolean running = true;
static { static {
// Configure logging // Configure logging
@@ -59,17 +63,19 @@ public MdgaServer(int port) {
*/ */
public void run() { public void run() {
startServer(); startServer();
while (true) while (running) {
processNextMessage(); processNextMessage();
}
shutdownServerResources();
} }
/** /**
* * Starts the server and initializes listeners.
*/ */
private void startServer() { private void startServer() {
try { try {
LOGGER.log(Level.INFO, "Starting server..."); //NON-NLS LOGGER.log(Level.INFO, "Starting server...");
unlockSerializers();//NON-NLS
myServer = Network.createServer(port); myServer = Network.createServer(port);
initializeSerializables(); initializeSerializables();
myServer.start(); myServer.start();
@@ -77,20 +83,22 @@ private void startServer() {
LOGGER.log(Level.INFO, "Server started: {0}", myServer.isRunning()); //NON-NLS LOGGER.log(Level.INFO, "Server started: {0}", myServer.isRunning()); //NON-NLS
} catch (IOException e) { } catch (IOException e) {
LOGGER.log(Level.ERROR, "Couldn't start server: {0}", e.getMessage()); //NON-NLS LOGGER.log(Level.ERROR, "Couldn't start server: {0}", e.getMessage()); //NON-NLS
exit(1); exit();
} }
} }
private void processNextMessage() { private void processNextMessage() {
try { try {
pendingMessages.take().process(logic); ReceivedMessage message = pendingMessages.take(); // This is a blocking call
message.process(logic);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
LOGGER.log(Level.INFO, "Interrupted while waiting for messages"); //NON-NLS LOGGER.log(Level.INFO, "Server thread interrupted, shutting down..."); //NON-NLS
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }
private void initializeSerializables() { private void initializeSerializables() {
Serializer.registerClass(UUID.class, new UUIDSerializer()); Serializer.registerClass(UUID.class, new UUIDSerializer());
Serializer.registerClass(AnimationEndMessage.class); Serializer.registerClass(AnimationEndMessage.class);
Serializer.registerClass(ClientStartGameMessage.class); Serializer.registerClass(ClientStartGameMessage.class);
@@ -262,12 +270,12 @@ public void handleDisconnect(int id) {
this.logic.received(new DisconnectedMessage(), id); this.logic.received(new DisconnectedMessage(), id);
} }
public void exit(int exitValue) { //NON-NLS /**
LOGGER.log(Level.INFO, "close request"); //NON-NLS * Stops the server thread gracefully.
if (myServer != null) */
for (HostedConnection client : myServer.getConnections()) //NON-NLS public void exit() {
if (client != null) client.close("Game over"); //NON-NLS LOGGER.log(Level.INFO, "Requesting server shutdown"); //NON-NLS
System.exit(exitValue); running = false;
} }
/** /**
@@ -309,7 +317,11 @@ public void broadcast(ServerMessage message) {
*/ */
@Override @Override
public void disconnectClient(int id) { public void disconnectClient(int id) {
this.myServer.getConnection(id).close(""); if (myServer.getConnection(id) != null) {
this.myServer.getConnection(id).close("");
} else {
LOGGER.log(Level.ERROR, "no connection with id={0}", id); //NON-NLS
}
} }
/** /**
@@ -319,13 +331,33 @@ public void disconnectClient(int id) {
*/ */
@Override @Override
public void shutdown() { public void shutdown() {
for (HostedConnection client : this.myServer.getConnections()) { this.exit();
if (client != null) { }
client.close("Host closed the server.");
}
}
this.myServer.close(); /**
this.exit(0); * Gracefully shutdown server resources like connections and sockets.
*/
private void shutdownServerResources() {
LOGGER.log(Level.INFO, "Shutting down server resources"); //NON-NLS
if (myServer != null && myServer.isRunning()) {
for (HostedConnection client : myServer.getConnections()) {
if (client != null) client.close("Server shutting down.");
}
myServer.close();
}
}
/**
* This method will be used to unlock the Serializer registry.
*/
private static void unlockSerializers() {
try {
Field lockField = Serializer.class.getDeclaredField("locked");
lockField.setAccessible(true);
lockField.setBoolean(null, false); // Unlock the Serializer registry
} catch (NoSuchFieldException | IllegalAccessException e) {
System.err.println("Failed to unlock the Serializer registry: " + e.getMessage());
e.printStackTrace();
}
} }
} }

View File

@@ -1,8 +1,12 @@
package pp.mdga.client; package pp.mdga.client;
import pp.mdga.Resources;
import pp.mdga.client.ceremonystate.CeremonyStates; import pp.mdga.client.ceremonystate.CeremonyStates;
import pp.mdga.client.ceremonystate.PodiumState; import pp.mdga.client.ceremonystate.PodiumState;
import pp.mdga.client.ceremonystate.StatisticsState; import pp.mdga.client.ceremonystate.StatisticsState;
import pp.mdga.message.server.ShutdownMessage;
import pp.mdga.notification.InfoNotification;
import pp.mdga.notification.StartDialogNotification;
public class CeremonyState extends ClientState { public class CeremonyState extends ClientState {
@@ -77,6 +81,11 @@ public CeremonyStates getState() {
return currentState; return currentState;
} }
@Override
public void received(ShutdownMessage msg){
logic.addNotification(new InfoNotification(Resources.stringLookup("server.shutdown")));
}
/** /**
* this method is used to parse the selectNext from the clientGameLogic * this method is used to parse the selectNext from the clientGameLogic
*/ */

View File

@@ -401,9 +401,7 @@ public void received(ServerStartGameMessage msg) {
*/ */
@Override @Override
public void received(ShutdownMessage msg) { public void received(ShutdownMessage msg) {
addNotification(new InfoNotification(Resources.stringLookup("server.shutdown"))); state.received(msg);
addNotification(new StartDialogNotification());
setState(dialogsState);
} }
/** /**

View File

@@ -1,9 +1,12 @@
package pp.mdga.client; package pp.mdga.client;
import pp.mdga.Resources;
import pp.mdga.game.BonusCard; import pp.mdga.game.BonusCard;
import pp.mdga.game.Color; import pp.mdga.game.Color;
import pp.mdga.game.Piece; import pp.mdga.game.Piece;
import pp.mdga.message.server.*; import pp.mdga.message.server.*;
import pp.mdga.notification.InfoNotification;
import pp.mdga.notification.StartDialogNotification;
import java.lang.System.Logger.Level; import java.lang.System.Logger.Level;
@@ -161,7 +164,9 @@ public void received(ServerStartGameMessage msg) {
@Override @Override
public void received(ShutdownMessage msg) { public void received(ShutdownMessage msg) {
LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg.toString()); logic.addNotification(new InfoNotification(Resources.stringLookup("server.shutdown")));
logic.addNotification(new StartDialogNotification());
logic.setState(logic.getDialogs());
} }
@Override @Override

View File

@@ -141,11 +141,9 @@ public void received(LobbyPlayerJoinedMessage msg) {
System.out.println(msg.getId()); System.out.println(msg.getId());
logic.setOwnPlayerId(msg.getId()); logic.setOwnPlayerId(msg.getId());
} }
if (msg.isHost() && msg.getId() == logic.getOwnPlayerId()) { if (msg.getPlayer().getColor() != Color.NONE){
logic.setHost(true); logic.addNotification(new TskSelectNotification(msg.getPlayer().getColor(), msg.getPlayer().getName(), msg.getPlayer().getName().equals(logic.getOwnPlayerName())));
} }
logic.addNotification(new TskSelectNotification(msg.getPlayer().getColor(), msg.getPlayer().getName(), msg.getPlayer().getName().equals(logic.getOwnPlayerName())));
logic.getGame().getPlayers().put(msg.getId(), msg.getPlayer()); logic.getGame().getPlayers().put(msg.getId(), msg.getPlayer());
} }

View File

@@ -2,6 +2,7 @@
import pp.mdga.game.Color; import pp.mdga.game.Color;
import pp.mdga.message.server.CeremonyMessage; import pp.mdga.message.server.CeremonyMessage;
import pp.mdga.message.server.ShutdownMessage;
import pp.mdga.server.ServerGameLogic; import pp.mdga.server.ServerGameLogic;
/** /**
@@ -59,6 +60,7 @@ private CeremonyMessage createCeremonyMessage() {
public void enter() { public void enter() {
LOGGER.log(System.Logger.Level.DEBUG, "Entered CeremonyState state."); LOGGER.log(System.Logger.Level.DEBUG, "Entered CeremonyState state.");
logic.getServerSender().broadcast(createCeremonyMessage()); logic.getServerSender().broadcast(createCeremonyMessage());
logic.getServerSender().shutdown();
} }
/** /**

View File

@@ -86,9 +86,9 @@ public void received(LeaveGameMessage msg, int from) {
this.logic.getServerSender().broadcast(new ShutdownMessage()); this.logic.getServerSender().broadcast(new ShutdownMessage());
this.logic.getServerSender().shutdown(); this.logic.getServerSender().shutdown();
} }
this.logic.getServerSender().disconnectClient(from);
this.logic.getGame().removePlayer(from); this.logic.getGame().removePlayer(from);
this.logic.getServerSender().broadcast(new LobbyPlayerLeaveMessage(from)); this.logic.getServerSender().broadcast(new LobbyPlayerLeaveMessage(from));
this.logic.getServerSender().disconnectClient(from);
} }
/** /**