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;
main.getJoinDialog().disconnect();
main.getHostDialog().shutdownServer();
System.out.println("Disconnecting from server..." + clientGameLogic.isHost());
if (clientGameLogic.isHost()) {
main.getHostDialog().shutdownServer();
}
ceremonyView.afterGameCleanup();
}

View File

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

View File

@@ -15,6 +15,9 @@
import java.io.IOException;
import java.lang.System.Logger;
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.UUID;
import java.util.concurrent.BlockingQueue;
@@ -31,6 +34,7 @@ public class MdgaServer implements MessageListener<HostedConnection>, Connection
private static int port;
private final ServerGameLogic logic;
private final BlockingQueue<ReceivedMessage> pendingMessages = new LinkedBlockingQueue<>();
private volatile boolean running = true;
static {
// Configure logging
@@ -59,17 +63,19 @@ public MdgaServer(int port) {
*/
public void run() {
startServer();
while (true)
while (running) {
processNextMessage();
}
shutdownServerResources();
}
/**
*
* Starts the server and initializes listeners.
*/
private void startServer() {
try {
LOGGER.log(Level.INFO, "Starting server..."); //NON-NLS
LOGGER.log(Level.INFO, "Starting server...");
unlockSerializers();//NON-NLS
myServer = Network.createServer(port);
initializeSerializables();
myServer.start();
@@ -77,20 +83,22 @@ private void startServer() {
LOGGER.log(Level.INFO, "Server started: {0}", myServer.isRunning()); //NON-NLS
} catch (IOException e) {
LOGGER.log(Level.ERROR, "Couldn't start server: {0}", e.getMessage()); //NON-NLS
exit(1);
exit();
}
}
private void processNextMessage() {
try {
pendingMessages.take().process(logic);
ReceivedMessage message = pendingMessages.take(); // This is a blocking call
message.process(logic);
} 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();
}
}
private void initializeSerializables() {
Serializer.registerClass(UUID.class, new UUIDSerializer());
Serializer.registerClass(AnimationEndMessage.class);
Serializer.registerClass(ClientStartGameMessage.class);
@@ -262,12 +270,12 @@ public void handleDisconnect(int id) {
this.logic.received(new DisconnectedMessage(), id);
}
public void exit(int exitValue) { //NON-NLS
LOGGER.log(Level.INFO, "close request"); //NON-NLS
if (myServer != null)
for (HostedConnection client : myServer.getConnections()) //NON-NLS
if (client != null) client.close("Game over"); //NON-NLS
System.exit(exitValue);
/**
* Stops the server thread gracefully.
*/
public void exit() {
LOGGER.log(Level.INFO, "Requesting server shutdown"); //NON-NLS
running = false;
}
/**
@@ -309,7 +317,11 @@ public void broadcast(ServerMessage message) {
*/
@Override
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
public void shutdown() {
for (HostedConnection client : this.myServer.getConnections()) {
if (client != null) {
client.close("Host closed the server.");
}
}
this.exit();
}
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;
import pp.mdga.Resources;
import pp.mdga.client.ceremonystate.CeremonyStates;
import pp.mdga.client.ceremonystate.PodiumState;
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 {
@@ -77,6 +81,11 @@ public CeremonyStates getState() {
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
*/

View File

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

View File

@@ -1,9 +1,12 @@
package pp.mdga.client;
import pp.mdga.Resources;
import pp.mdga.game.BonusCard;
import pp.mdga.game.Color;
import pp.mdga.game.Piece;
import pp.mdga.message.server.*;
import pp.mdga.notification.InfoNotification;
import pp.mdga.notification.StartDialogNotification;
import java.lang.System.Logger.Level;
@@ -161,7 +164,9 @@ public void received(ServerStartGameMessage msg) {
@Override
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

View File

@@ -141,11 +141,9 @@ public void received(LobbyPlayerJoinedMessage msg) {
System.out.println(msg.getId());
logic.setOwnPlayerId(msg.getId());
}
if (msg.isHost() && msg.getId() == logic.getOwnPlayerId()) {
logic.setHost(true);
if (msg.getPlayer().getColor() != Color.NONE){
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());
}

View File

@@ -2,6 +2,7 @@
import pp.mdga.game.Color;
import pp.mdga.message.server.CeremonyMessage;
import pp.mdga.message.server.ShutdownMessage;
import pp.mdga.server.ServerGameLogic;
/**
@@ -59,6 +60,7 @@ private CeremonyMessage createCeremonyMessage() {
public void enter() {
LOGGER.log(System.Logger.Level.DEBUG, "Entered CeremonyState state.");
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().shutdown();
}
this.logic.getServerSender().disconnectClient(from);
this.logic.getGame().removePlayer(from);
this.logic.getServerSender().broadcast(new LobbyPlayerLeaveMessage(from));
this.logic.getServerSender().disconnectClient(from);
}
/**