Concepts / Networked TicTacToe Game

Networked TicTacToe Game

The Hub is the single authoritative source for the TicTacToe game, and both network players connect to it.

  • Programming

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
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.

Player Asends movesHublistens on a portTicTacToeGameStateofficial game recordPlayer Bsends movesprivate field statesends messagessends messagessends updated statesends updated state
Why do both players connect to the same Hub instead of to each other, and what does each machine hold versus what lives only on the Hub?

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.

Key point

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.

Player AHubPlayer Bmove messagestate.applyMessage()updated stateupdated state
After one player clicks a square, which machine handles the move first, and which machines receive the updated board?
Worked example

Tracing Player A's Move

Player A clicks a square. Trace what the Hub does with the message and who receives the result.

  1. 1
    Message 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.

  2. 2
    Hub 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.

  3. 3
    State 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.

  4. 4
    Updated 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.

Result

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.

java
Notes on the code
  • 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 port
  • setAutoreset(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.

Message from aclientHub callsstate.applyMessage()Game state updatedAutoreset enabled?Output stream resetbefore each messageUpdated state sent toboth playersStream not resetchanged contents may not berewrittenyesnodivergence risk
At which branch in the Hub's handling of an incoming message could the board sent to players stop matching the board the rules expect?
  • Common mistake

    Assuming each player's machine owns the board

    Why it fails

    The source states that the Hub holds the single official record, and each player's machine is not the authority on the board.

    Do this instead

    Look to the Hub first when the two players disagree about the board.

  • Common mistake

    Editing the board directly in the network code

    Why it fails

    The state is never edited directly by the network code. It is updated by applying messages through state.applyMessage().

    Do this instead

    Route 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 fails

    Autoreset controls the output stream before each message is sent, not how moves are judged.

    Do this instead

    Treat 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

MEDIUM

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 calls setAutoreset(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.