This project aims to build a decentralized, serverless multiplayer game engine by developing a custom Reliable UDP (RUDP) protocol. Since TCP is too slow for real-time games and standard UDP drops critical state updates, our custom transport layer guarantees the delivery of important game events without needing a central host.
- P2P Game Client: Developed using Raylib and C++, featuring a peer-to-peer ring topology.
- Custom Transport Protocol (RUDP): Developed from scratch over raw UDP, featuring a 16-byte header, sliding windows with Go-Back-N/cumulative ACKs, Jacobson/Karels RTT estimators, and NAT traversal.
- Benchmarking Suite: Tools to benchmark and compare RUDP's latency and reliability against standard TCP and UDP under simulated network packet loss.
- Wireshark Integration: Custom Lua dissector to demonstrate packet formats live in Wireshark.
g++ game.cpp -o game.out -lraylib -pthread -std=c++17
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
./game.outraylibpthreadlinux-kernel >= 6.1x.xx(For Windows, replacearpa/inetwithwinsock)
- Iterative DNS-inspired Discovery:
- Host is requested.
- If the host's
nextpointer is empty, you become itsnextpointer. - If occupied, the request is redirected further down the chain.
- The chain connects back to the head to form a complete Peer-to-Peer Ring (🍐2🍐).
- Game Data Exchange:
- All peers communicate with their
.nextpeer. - Scores are broadcasted down the network chain until resolving back to the origin.
- All peers communicate with their
User can switch protocols via the Menu:
TCP-> Standard reliable but high overhead.UDP-> Unreliable default.Custom (RUDP)-> Our custom protocol utilizing Go-Back-N (Window Size: 10,000).
While the game client integrates custom rudp.hpp, we have also provided a fully decoupled robust implementation in the /rudp and /transport directories.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Ver | Flags | Payload Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Header = 16 bytes. Flags: SYN ACK FIN RST PING PONG NAT DATA
For full details on the State Machine, RTT Estimation, Flow Control, and Checksum calculations, please refer to PROTOCOL.md.
We provide a complete suite of standard C tools to evaluate throughput, latency, and reliability in simulated lossy environments.
# 1. Start packet loss simulation (Using Linux tc netem)
sudo bash tools/tc_netem.sh setup 20 # 20% Packet Loss
# 2. Run Receiver and Sender (Using the Makefile to build fully decoupled tools)
make benchmark
./bench_receiver --proto rudp --port 9001 --count 1000 &
./bench_sender --proto rudp --host 127.0.0.1 --port 9001 --count 1000 --size 512
# 3. Generate Evaluation Report
python3 benchmark/bench_report.py --proto RUDP --size 512
# 4. Remove rules
sudo bash tools/tc_netem.sh teardown| Feature | Standard UDP | TCP | RUDP |
|---|---|---|---|
| Header size | 8 bytes | 20 bytes | 16 bytes |
| Reliability | None | ACK + retransmit | ACK + retransmit |
| Ordering | None | Strict In-Order | Sliding window |
| RTT estimation | None | Standard | Jacobson/Karels |
| Congestion Control | None | Window-based Slow Start | Window-based Flow Control |
| Head-of-line blocking | No | Yes | No |
To easily demonstrate to the evaluator that our Protocol is actively on the wire, check out WIRESHARK.md for custom display filters and the Lua Dissector code.
Quick Wireshark Display Filter:
udp.port == 9000 || udp.port == 9001
Note for maintainers: The Game UI is tightly coupled to the P2P networking state machine. Do not modify component screen transitions without understanding the full peer discovery handshake flow.