I am trying to write a game server that supports multiplayer over a network.
What I am attempting to achieve is a server that listens in a loop for connections and sets up a thread for each client. it should do this until the host of the game clicks start game, upon which it should continue with the game logic, sending data etc.
To achieve this I use this code in the run method of this thread to loop and listen for connections.
try {
while (gameStarted == false) {
System.out.print(gameStarted);
clientSocket = ss.accept();
ClientThreadOnServer runClient = new ClientThreadOnServer(clientSocket);
clientThreads.add(runClient);
window.updateText();
}
System.out.println("end");
Within my server I then placed an runnable inner class that pops up a JFrame with a counter and a start button, with the idea being the boolean gameStarted gets 开发者_运维问答flipped when the user clicks start game in the frame, like so:
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("start")) {
synchronized (this) {
System.out.println("click");
gameStarted = true;
}
}
}
however it doesn't work! When you click start the button is detected and pressed so presumably the boolean is changed, but the server doesn't exit the while loop and continue on. I think I know why, the loop is sitting on ss.accept(); and not testing the boolean condition as I had hoped.
I'm not really sure if I am even going about this in the right way, especially the list of client threads on the server which I hope to then use to control the sending of data. If I am doing this in a totally wrong way please let me know how it should be done, or if I am not crazy, how do I make my code work?
accept()
-
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
This means that the loop will only check the game state right after a client has connected. You can use setTimeout()
to specify the how long an accept call can block for before throwing a SocketTimeoutException
to signify that a client did not connect. You can use that in your loop to cause accept()
to not block forever and allow you to check gameStarted
again.
Note:
You are not fully synchronizing on gameStarted
, just on the write. This means there is a race condition and you might attempt to accept an additional client after start is clicked. The easiest way to fix this is with the following. You don't want to put the entire loop in a synchronized block because then the start button would never be able to enter it's synchronized block because the loop is holding the lock.
private synchronized boolean isGameStarted() {
return gameStarted;
}
...
try {
while (!isGameStarted()) {
...
精彩评论