Networked TicTacToe Game
The Hub is the single authoritative source for the TicTacToe game, and both network players connect to it.
Predicting Who Owns the Board
This article starts from running code rather than from definitions. The TicTacToeGameHub class is the central piece of a networked TicTacToe game, and its behavior is easiest to understand by watching what it does when messages arrive. As you read, notice each point where the program's behavior is decided, because those are the places where a wrong result would have to come from.
What do you think happens?
Two people are playing TicTacToe over a network. Before reading on, make a guess: who keeps the official version of the game, and who has to be told when the board changes?
Reveal answer
The Hub keeps the official version of the game, and it sends each change to both players.
The class extends a Hub, and the Hub is the single authoritative source for the game. Each player's own machine is not the authority on the board.
Why Both Players Connect to One Hub
The reason for one shared Hub is consistency. Official information about the state of the game is maintained on the Hub. Each player's own machine is not the authority on the board. Instead, the Hub holds the single official record, and when that record changes, the Hub sends the new state to both players. Because both players receive the same updates from the same place, they see the same state.
The diagram shows the two directions of traffic. Messages travel inward from each client to the Hub, and updated state travels outward from the Hub to both clients. The game state object lives on the Hub, not on either client. The Hub stores the game in a field declared as private TicTacToeGameState state, and this field is the record of the game's state. The Hub is therefore the only place where the game state is changed, which makes it the natural place to look when two players disagree about the board.
The Hub is the single authoritative source for the game. Both players connect to it, and they see the same board because they receive the same updates from the same place.
Tracing a Move Through the Hub
Follow one move from start to finish. The sequence below shows which machine sees the move first and which machines receive the updated board.
Tracing Player A's Move
Player A clicks a square. Trace what the Hub does with the message and who receives the result.
- 1Message arrives at the Hub
The move travels inward from Player A to the Hub. Messages from clients always arrive at the Hub, not at the other player.
- 2Hub passes the message to the state
The Hub's message-handling method calls
state.applyMessage()with the incoming message. The Hub does not edit the board itself. - 3State object decides what the move means
The TicTacToeGameState object applies the rules of the game to the message. The source describes this split: the Hub handles communication, and the state handles the rules.
- 4Updated state is sent outward
After the state is updated, the Hub sends the result onward to both Player A and Player B, so both see the same board.
One move produces one update to the single official state on the Hub, and that update reaches both players.
The Constructor and setAutoreset(true)
The class header shows that TicTacToeGameHub extends Hub, so it inherits the general networking behavior of a Hub and adds the TicTacToe-specific parts. The constructor takes a port number, which is the port on which the Hub listens for connections. Three things happen in the constructor, in this order: the parent Hub is set up with the port through super(port), a new TicTacToeGameState object is created, and setAutoreset(true) is called.
- extends Hub: inherits the general networking behavior of a Hub
- private field state: the Hub's single record of the game
super(port): sets up the parent Hub to listen on the portsetAutoreset(true): called last in the constructor
Autoreset controls what happens to the output stream each time a message is sent. According to the source, setAutoreset(true) causes the output stream to each client to be reset before each message is sent. The source calls this essential, and the reason is specific to this design. The Hub does not build a new state object for every update. It keeps sending the same TicTacToeGameState object, and the contents of that object change between transmissions.
Think about what the client would see if the stream were not reset. The client reads a stream of objects sent by the Hub. If the same object is sent again after it has changed, the stream must be told to write the new contents rather than treating the object as already sent. Autoreset is the mechanism that makes each transmission of the changed object an accurate picture of the current game. The source does not go beyond this description, so the details of how the stream reset is carried out belong to the underlying network library, not to this class.
Where a Faulty Game Would Diverge
If two players ever see different boards, the cause must be in the path a message takes through the Hub, because that path is the only place where the state changes and the updates are sent out. The flowchart below marks the branches where the board sent to players could stop matching the board the rules expect.
Common mistake Assuming each player's machine owns the board
Why it failsThe source states that the Hub holds the single official record, and each player's machine is not the authority on the board.
Do this insteadLook to the Hub first when the two players disagree about the board.
Common mistake Editing the board directly in the network code
Why it failsThe state is never edited directly by the network code. It is updated by applying messages through
state.applyMessage().Do this insteadRoute every change through the message path so the state object applies the game rules.
Common mistake Thinking setAutoreset(true) changes the rules of the game
Why it failsAutoreset controls the output stream before each message is sent, not how moves are judged.
Do this insteadTreat autoreset as a transmission detail that keeps repeated sends of the changing state accurate.
Common mistake Believing the Hub builds a new state object for every update
Practice: Locating the Divergence
A networked TicTacToe game shows Player A a board with an X in the top-left square, but Player B's screen shows no X there. Using only the Hub's message path, name the component that should be checked first, the method call that applies the move, and the step where the two screens could have separated. Explain your answer in terms of the Hub being the single authoritative source.
Hints
- Ask which object holds the official record of the game.
- Follow the message from the moment it arrives at the Hub to the moment the updated state is sent to both players.
- Check whether the output stream is being reset before each message, using the autoreset behavior described above.
Key Takeaways
- The Hub is the single authoritative source for the TicTacToe game, and both network players connect to it so they receive the same updates from the same place.
- A client message arrives at the Hub, the Hub calls
state.applyMessage(), and the updated TicTacToeGameState is sent to both players. - The constructor calls
super(port), creates the TicTacToeGameState, and callssetAutoreset(true), which resets the output stream to each client before each message. - A faulty game would diverge in the Hub's message handling, since the Hub is the only place where the game state object is changed and then sent out.