Grid State Synchronization Protocol (GSSP)
- Multiplayer Network Game – Phase 2
This project is a UDP-based multiplayer grid game developed as part of the Networking Course Project – Phase 2. It extends the Phase 1 prototype by implementing a reliable, event-driven synchronization protocol (GSSP) with Selective Repeat ARQ, a waiting room system, leaderboard, and automated network testing.
The server acts as an authoritative node, maintaining the global grid state and synchronizing all connected clients using delta-based board snapshots. Communication is optimized for low latency and bandwidth efficiency, even under packet loss and delay.
To achieve real-time performance while ensuring game state consistency, the system employs several specific architectural patterns and protocol designs.
- Decision: Use UDP instead of TCP.
- Reasoning: TCP enforces strict ordering and retransmission, leading to Head-of-Line (HOL) blocking. In a real-time game, waiting for a lost packet to arrive before processing newer packets causes perceptible lag.
- Decision: Implement Selective Repeat Automatic Repeat Request (ARQ).
- Reasoning: Simple "Stop-and-Wait" is too slow, and "Go-Back-N" wastes bandwidth by resending already-received packets.
- Mechanism:
- The sender maintains a window of unacknowledged packets.
- The receiver acknowledges packets individually.
- Only specific lost packets are retransmitted after a per-packet timer expires, optimizing bandwidth usage under simulated packet loss (e.g.,
netem5% loss).
- Decision: Server is the single source of truth.
- Reasoning: Peer-to-peer architectures are prone to race conditions (two players claiming a cell simultaneously) and cheating.
- Mechanism: Clients send
CLAIM_REQUESTintents. The server processes these sequentially. If valid, the server updates the state and broadcasts aBOARD_SNAPSHOT. If invalid (e.g., cell already taken), the request is ignored or rejected, ensuring all clients eventually converge on the server's state.
- Decision: Send updates on state change only (Event-Driven), rather than a fixed tick rate (e.g., 60Hz streaming).
- Reasoning: Streaming the full board continuously consumes unnecessary bandwidth, especially when the grid is static.
- Mechanism: The server broadcasts
BOARD_SNAPSHOTmessages only when a player successfully claims a cell or the game phase changes. This "Delta" approach significantly reduces network load.
-
Custom UDP protocol (GSSP) with:
- Sequence numbers
- Acknowledgments
- Selective Repeat ARQ
- Per-packet timers
-
Waiting Room System:
- Minimum 2 players required to start
- 1-minute countdown once minimum players join
- Start Now option to skip waiting
-
Real-time Grid Gameplay:
- Players can claim cells
- Players can reclaim cells from other players
-
Fixed game duration (100 seconds)
-
End-game Leaderboard popup
-
“Play Again” support (returns players to waiting room)
-
Automated testing under packet loss and delay using
netem -
CSV logging and performance metrics collection
.
├── launcher.py # Starts server and launches clients
├── server.py # Authoritative game server
├── client.py # Game client
├── protocol.py # GSSP message formats & helpers
├── waiting_room.py # Waiting room logic
├── leaderboard.py # End-game leaderboard popup
├── gui.py # Game GUI components
├── tests
│ ├── run_all_tests.sh # Automated netem test runner
│ ├── analyze_results.py # Post-test CSV analysis
│ ├── generate_plots.py # Generate graphs from test results
│ ├── postprocess.py # Data postprocessing utilities
│ ├── test_client.py # Unit tests for client
│ └── test_server.py # Unit tests for server
│ └── results
| ├── logs # CSV logs (latency, jitter, error)
└── README.md
-
Python 3.8+
-
Linux environment (for
tc netemtesting) -
Standard Python libraries:
socketstructtimethreadingselect
No external Python dependencies are required.
launcher.pystarts the server- Clients are launched from the launcher interface
-
Players enter a waiting room upon joining
-
Game starts when:
-
At least 2 players are present, and
-
Either:
- The 1-minute timer expires, or
- A player clicks Start Now
-
- Duration: 100 seconds
- Players send CLAIM_REQUEST messages to claim or steal grid cells
- Server validates actions and broadcasts BOARD_SNAPSHOT updates
- Clients update their local view using received snapshots
- Server sends GAME_OVER
- Leaderboard popup shows final rankings
- Players may choose Play Again, returning to the waiting room
- Transport: UDP
- Model: Client–Server
- Reliability: Selective Repeat ARQ
- Update Strategy: Event-driven (no periodic streaming)
| MsgType | Description |
|---|---|
| 0 | JOIN_REQUEST |
| 1 | JOIN_RESPONSE |
| 2 | CLAIM_REQUEST |
| 3 | BOARD_SNAPSHOT |
| 4 | GAME_OVER |
| 5 | LEAVE |
| 6 | GAME START |
| 7 | WAITING_ROOM |
| 8 | ACK |
| 9 | LEADERBOARD |
Each message includes:
- Sequence number
- Acknowledgment number
- Snapshot ID
- Timestamp
- Variable payload
for mac : python3 launcher.py
for windows: python launcher.py- Click Start Server from the launcher
- Click New Client
- Each client joins the waiting room automatically
- Wait for the minimum players or click Start Now
All tests are automated using Linux netem.
2% Packet Loss sudo tc qdisc add dev root netem loss 2%
5% Packet Loss sudo tc qdisc add dev root netem loss 5%
100 ms Delay sudo tc qdisc add dev root netem delay 100ms
Remove netem: sudo tc qdisc del dev root
Automated Test Execution cd tests ./run_all_tests.sh
Each test produces CSV logs with:
client_idsnapshot_idseq_numserver_timestamp_msrecv_time_mslatency_msjitter_msperceived_position_errorcpu_percentbandwidth_per_client_kbps
Reported statistics:
- Mean
- Median
- 95th percentile
| Scenario | Result |
|---|---|
| Baseline | ≤ 50 ms latency, stable CPU |
| 2% Loss | low error |
| 5% Loss | ≥ 99% critical event delivery |
| 100 ms Delay | Stable gameplay, no desync |
- Server must be started before clients
- Communication uses UDP over localhost
- Snapshots are sent only on state changes
- Logs are generated for testing and evaluation