This is a sample learning project where I delved into the working principles of the network & transport layer with particular focus on the UDP(User Datagram Protocol).
This project demonstrates how to add TCP-like reliability guarantees (acknowledgments, retransmission, ordering) to UDP's speed and simplicity.
The aim is to create a rust project that uses tokio and async rust to test and understand how UDP works and then improve on its shortcomings
This is an educational project designed to build deep understanding of:
- Transport layer protocols (TCP, UDP, QUIC)
- Network reliability mechanisms (sequence numbers, ACKs, timeouts)
- Async networking in Rust (Tokio, async/await)
- Blockchain networking fundamentals (Solana validator communication, gossip protocols) By building reliability from scratch, I gain insight into how production protocols like QUIC work and how Solana validators communicate efficiently.
This is a reliable UDP implemetation that gives the speed of UDP together with reliablity, retransmission and certainty of TCP. In Relic UDP we have:
- Sequence numbers for packet ordering
- Acknowledgments (ACKs) to confirm delivery
- Timeouts & retransmission for handling packet loss
- Flow control for managing sender/receiver speeds
UDP is connectionless, stateless and fast. There are short comings while using UDP, like packet rearrangement, loss etc. So Relic UDP will contain retransmission, Acknowledgement as well as speed
┌─────────────┐ ┌─────────────┐
│ Client │ │ Server │
│ │ │ │
│ Protocol │ ←──── UDP ────→ │ Protocol │
│ Layer │ (unreliable) │ Layer │
│ │ │ │
│ Tokio UDP │ │ Tokio UDP │
│ Socket │ │ Socket │
└─────────────┘ └─────────────┘
Components:
- protocol.rs: Packet serialization/deserialization, message types
- client.rs: Sender logic with retransmission
- server.rs: Receiver logic with ACK generation
- Sequence Numbers: Each packet gets a unique number to track order and detect duplicates/loss
- Acknowledgments (ACKs): Receiver confirms each packet received by sending ACK with sequence number
- Timeouts: If no ACK received within timeout period, sender retransmits the packet
- Retransmission: Lost packets are automatically resent based on timeout or negative ACK
Implemented:
- Basic UDP client/server communication
- Packet structure with sequence numbers
- Serialization/deserialization (to_bytes/from_bytes)
- Unit tests for protocol layer
In Progress:
- ACK message type
- Timeout & retransmission logic
- Packet loss simulation
Future:
- Go-Back-N sliding window protocol
- Selective Repeat ARQ
- Flow control (window size management)
- Congestion control
- Custom UDP implementation from scratch (using tun/tap)
- Rust 1.70+ (with Cargo)
- Linux/macOS/WSL (for full feature support)
git clone https://github.com/AlphaR2/Relic-UDP.git
cd Relic-UDP
cargo buildcargo run --bin serverExpected output:
=================================
🚀 RELIABLE UDP SERVER
=================================
Server listening on: 127.0.0.1:8080
RECEIVED Packet #1 from 127.0.0.1:xxxxx
Data: "Hello from packet #1"
ECHOED Packet #1 back
# In a separate terminal
cargo run --bin clientExpected output:
=================================
📡 RELIABLE UDP CLIENT
=================================
Client: 127.0.0.1:xxxxx
Server: 127.0.0.1:8080
SENDING Packet #1: Hello from packet #1
RECEIVED Packet #1: "Hello from packet #1"
SENDING Packet #2: Hello from packet #2
RECEIVED Packet #2: "Hello from packet #2"
...
All packets sent successfully!
Current implementation (Data packet):
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number (u32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data (variable length) |
| ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Sequence Number: 4 bytes (big-endian), tracks packet order
- Data: Variable length payload (text, binary, any data)
Current:
- DATA Packet: Contains sequence number + payload data
Coming: 2. ACK Packet: Acknowledgment with sequence number 3. NACK Packet: Negative acknowledgment for explicit retransmission
Basic Echo (Current):
Client Server
| |
|-----DATA Packet #1------------->|
| [seq: 1, data: "Hello"] |
| |
|<----Echo Packet #1--------------|
| [seq: 1, data: "Hello"] |
| |
With ACKs (Next Phase):
Client Server
| |
|-----DATA Packet #1------------->|
| [seq: 1, data: "Hello"] |
| |
|<----ACK #1----------------------|
| |
|-----DATA Packet #2------------->|
| [seq: 2, data: "World"] |
| |
|<----ACK #2----------------------|
| |
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Test specific module
cargo test protocol::testsCurrent tests:
test_packet_seri_deseri: Verifies packet serialization round-triptest_packet_with_empty_data: Tests edge case of empty payload
Speed over guarantees:
- No connection establishment overhead (vs TCP's 3-way handshake)
- Lower latency for time-sensitive applications
- Full control over reliability mechanism
- Matches Solana's networking approach (QUIC on UDP)
Learning opportunity:
- Understand the problems UDP has (packet loss, reordering, duplication)
- Implement solutions used in production protocols
- Appreciate what TCP provides for free
Stop-and-Wait (Current):
- Simplest to implement and understand
- Send one packet, wait for ACK, send next
- Great for learning fundamentals
Sliding Window (Future):
- Much better performance (send multiple packets before waiting)
- Used by TCP, QUIC, and other production protocols
- More complex but necessary for real-world use
1. Packet Buffering Issues
- Problem: Client receiving old packets from OS buffer
- Cause: UDP socket buffers incoming packets in kernel FIFO queue
- Learning: Discovered why sequence number checking is critical
- Solution: Next phase will implement ACK verification loop
2. Serialization Design
- Problem: Converting Rust structs to/from network bytes
- Solution: Used big-endian encoding for network byte order
- Learning: Understood why protocols specify byte order
3. Async Rust Learning Curve
- Problem: Understanding futures, .await, and Tokio runtime
- Solution: Started with simple examples, gradually added complexity
- Learning: Async is necessary for high-performance network code
Phase 2 Complete: Sequence Numbers
- Implemented Packet struct with seq_num field
- Built serialization/deserialization (to_bytes/from_bytes)
- Client sends numbered packets (1, 2, 3, 4, 5)
- Server decodes and echoes back with sequence numbers
- Discovered UDP buffering behavior
Phase 3 Next: ACKs & Verification
- Add Message enum (Data vs Ack)
- Server sends ACK after receiving packet
- Client waits for correct ACK before proceeding
- Implement ACK timeout and retry logic
- UDP echo server/client
- Tokio async networking
- Send/receive raw bytes
- Packet structure with seq_num
- Serialization/deserialization
- Numbered packet transmission
- ACK message type
- Sequence number verification
- Correct packet ordering
- Timeout detection
- Automatic retransmission
- Retry limits
- Go-Back-N protocol
- Multiple outstanding packets
- Window size management
- Flow control
- Congestion control
- Performance optimization
- Build UDP from scratch using tun/tap
- Implement IP layer
- Packet fragmentation
TCP
- Similarities: Both use sequence numbers, ACKs, retransmission
- Differences: TCP has connection state, more overhead, automatic flow control
- Relic-UDP: Lighter weight, explicit control over reliability
QUIC
- Similarities: UDP-based, multiplexing, modern design
- Differences: QUIC has encryption (TLS 1.3), connection migration, 0-RTT
- Relic-UDP: Educational simplification of QUIC concepts
TFTP
- Similarities: Simple reliable UDP, stop-and-wait protocol
- Differences: TFTP is for file transfer only
- Relic-UDP: General-purpose protocol learning
Why this matters for Solana(My major focus):
- Validator Networking: Solana uses QUIC (UDP-based) for transaction ingestion (TPU)
- Turbine Protocol: Block propagation uses UDP with erasure coding
- Gossip: Validator discovery and comm protocol
- Performance: Understanding UDP is key to understanding Solana's speed
Networking Fundamentals:
- Beej's Guide to Network Programming - UDP/TCP in C (concepts apply to Rust)
- [TCP vs UDP Crash Course by Hussein Nasser ] (https://youtu.be/qqRYkcta6IE?si=NCM3qwO6z3HcJxCk)
- [The OSI Model ] (https://youtu.be/7IS7gigunyI?si=d_o_M06iSJvnByPC)
Async Rust:
- Tokio Tutorial - Official async Rust networking guide
- Async Rust Book - In-depth async/await
- Jon Gjengset's Crust of Rust: async/await
Benchmarks coming in Phase 4 after timeout/retransmission
Planned metrics:
- Throughput vs TCP (Mbps)
- Latency comparison (RTT)
- Packet loss resilience (% loss vs delivery rate)
relic-udp/
├── src/
│ ├── server.rs # UDP server with packet decoding and echo
│ ├── client.rs # UDP client with numbered packet sending
│ └── protocol.rs # Packet struct, serialization, and tests
├── Cargo.toml # Dependencies (tokio)
├── README.md # This file
└── .gitignore
Status: 🚧 Active Development | Phase 2 Complete | Learning in Public
Last updated: 11/17/2025# Relic-UDP