A Python implementation of a reliable transport protocol built on top of UDP, demonstrating the fundamental mechanisms of TCP including connection management, sliding window flow control, error detection, and fast retransmission.
URP is a lightweight, educational implementation of a reliable transport protocol that brings reliability to UDP through:
- Two-way connection setup/teardown with handshaking
- Sliding window protocol for pipelined data transmission
- Selective repeat error recovery with fast retransmit on duplicate ACKs
- CRC-16 error detection for corruption detection
- Packet loss and corruption simulation for testing protocol robustness
- Real-time logging of all protocol events
Unlike TCP, URP is intentionally asymmetric with unidirectional data flow (Sender → Receiver) and reverse ACKs (Receiver → Sender), making it ideal for understanding reliable data transfer fundamentals without the complexity of bidirectional communication.
The Sender employs a multi-threaded architecture to handle concurrent events:
- Initiates connection setup (SYN, ACK handshake)
- Coordinates file transmission
- Manages connection teardown (FIN, ACK)
- Orchestrates all worker threads
- Pulls segments from the send queue
- Routes segments through the PLC (Packet Loss & Corruption) module
- Buffers segments for potential retransmission
- Manages segment serialization to UDP datagrams
- Listens for incoming ACK segments with timeout management
- Processes ACKs through reverse PLC path
- Validates segments using CRC-16 checksums
- Queues valid ACKs for processing
- Monitors timeout events every 10ms
- Triggers retransmission of oldest unacknowledged segment on timeout
- Updates segment timestamps post-retransmission
- Maintains protocol timing discipline
- Dequeues ACKs from the receive queue
- Tracks duplicate ACK counts
- Implements fast retransmit (immediate retransmission on 3 duplicate ACKs)
- Manages sliding window advancement
- Removes acknowledged segments from send buffer
The Receiver operates as a state machine with single main thread and optional timer thread:
- Listens for incoming segments in LISTEN state
- Validates segments via CRC-16
- Handles state transitions (LISTEN → ESTABLISHED → TIME_WAIT → CLOSED)
- Processes SYN, DATA, and FIN segments
- Manages out-of-order packet buffering
- Generates and sends ACK segments
- Writes received data to output file in order
- Manages 2 MSL (2-second) TIME_WAIT period
- Allows graceful handling of retransmitted FINs
- Signals main thread to transition to CLOSED state
Sender Receiver
|--- SYN (ISN) ------------->|
|<--- ACK (ISN+1) ----------|
(Connection Established)
- Sliding Window Protocol: Multiple segments transmitted in pipeline
- Selective Repeat: Out-of-order packets buffered at receiver
- Cumulative ACKs: Receiver ACKs the next expected byte
- Fast Retransmit: Sender retransmits on 3 duplicate ACKs
- Timeout Retransmission: Sender retransmits oldest unacknowledged segment
Sender Receiver
|--- FIN (seq+1) ---------->|
|<--- ACK (FIN+1) ---------|
(Connection Closed) (TIME_WAIT for 2 MSL)
(Connection Closed)
All URP segments follow a fixed 6-byte header:
Offset Bit 0-15 16-31 32-47
0 Sequence Number (16-bit) | Reserved (13-bit) | Flags (3-bit)
4 Error Detection (16-bit CRC)
6 Payload Data (0-1000 bytes)
Flags:
- DATA: No flag set (normal data segment)
- ACK: Acknowledgment segment
- SYN: Connection initiation
- FIN: Connection termination
URP implements CRC-16 (Cyclic Redundancy Check) for robust error detection:
Parameters:
- Generator Polynomial:
0x1021(x¹⁶ + x¹² + x⁵ + 1) - Initial CRC:
0xFFFF - Detection Capability: All single-bit errors, most multi-bit errors
Validation: Segments with invalid CRC checksums are silently discarded without ACK, triggering sender timeout and retransmission.
- Python 3.7+
- Linux environment (tested on VLAB)
Start Receiver first:
python3 receiver.py <receiver_port> <sender_port> <output_file> <window_size>Then start Sender:
python3 sender.py <sender_port> <receiver_port> <input_file> <window_size> <rto> <flp> <rlp> <fcp> <rcp>Receiver:
receiver_port: UDP port for receiving data (e.g., 56007)sender_port: UDP port of sender (e.g., 59606)output_file: Filename for received datawindow_size: Receive window in bytes (must match sender)
Sender:
sender_port: UDP port for sending (e.g., 59606)receiver_port: UDP port of receiver (e.g., 56007)input_file: File to transferwindow_size: Send window in bytes (≥1000, multiples of 1000)rto: Retransmission timeout in milliseconds (e.g., 100)flp: Forward loss probability [0.0-1.0] (e.g., 0.1 = 10% loss)rlp: Reverse loss probability [0.0-1.0]fcp: Forward corruption probability [0.0-1.0]rcp: Reverse corruption probability [0.0-1.0]
# Terminal 1: Start Receiver
python3 receiver.py 56007 59606 received_file.txt 1000
# Terminal 2: Start Sender (max_win=1000 = stop-and-wait)
python3 sender.py 59606 56007 input_file.txt 1000 100 0 0 0 0# Terminal 1: Start Receiver
python3 receiver.py 56007 59606 received_file.txt 4000
# Terminal 2: Start Sender (max_win=4000 = sliding window)
python3 sender.py 59606 56007 input_file.txt 4000 100 0.1 0.05 0.05 0.02
# This simulates: 10% forward loss, 5% reverse loss, 5% forward corruption, 2% reverse corruptionBoth Sender and Receiver generate detailed real-time logs:
Format: <direction> <status> <time> <segment-type> <seq-number> <payload-length>
Example:
snd ok 0.00 SYN 63999 0
rcv ok 103.21 ACK 64000 0
snd ok 104.52 DATA 64000 1000
snd ok 104.53 DATA 65000 1000
rcv ok 104.78 ACK 64000 0
snd drp 205.65 DATA 64000 1000
snd ok 310.16 DATA 64000 1000
rcv ok 310.58 ACK 1464 0
snd ok 310.95 FIN 1964 0
rcv ok 518.35 ACK 1965 0
Status Values:
ok: Segment transmitted/received without issuedrp: Segment dropped by PLC modulecor: Segment corrupted by PLC module
Sender Statistics:
- Original data sent (payload only)
- Total data sent (includes retransmissions)
- Original segments sent
- Total segments sent
- Timeout retransmissions
- Fast retransmissions
- Duplicate ACKs received
- Corrupted ACKs discarded
- PLC forward segments dropped/corrupted
- PLC reverse segments dropped/corrupted
Receiver Statistics:
- Original data received (payload only)
- Total data received
- Original segments received
- Total segments received
- Corrupted segments discarded
- Duplicate segments received
- Total ACKs sent
- Duplicate ACKs sent
- Locks:
state_lock,data_lock,stats_lock,log_lockensure atomic operations - Thread-safe Queues:
send_queue,ack_queueenable safe inter-thread communication
- Send Buffer: Dictionary mapping sequence numbers to segment data for retransmission
- Receive Buffer: Out-of-order packet storage with tracking of received sequence numbers
- Received Sequences Set: Efficient lookup for duplicate detection
The implementation has been validated across multiple scenarios:
- Stop-and-Wait on Reliable Channel (max_win=1000, no loss/corruption)
- Stop-and-Wait on Unreliable Channel (packet loss only, then corruption only, then both)
- Sliding Window on Reliable Channel (max_win=2000-10000)
- Sliding Window on Unreliable Channel (various combinations of loss/corruption)
Expected Behavior:
- File integrity verified via
diffcommand - Logs match protocol state transitions
- Statistics accurately reflect protocol events
- Protocol converges even with loss/corruption probabilities < 1.0
-
Multi-threading for Sender: Enables concurrent handling of segment transmission, receiving, timeout management, and ACK processing without artificial delays.
-
Single-threaded Receiver: Simplifies state management; timer thread added only for TIME_WAIT period.
-
CRC-16 Error Detection: Chosen for educational value and effectiveness at transport layer, despite traditionally being a data-link layer function.
-
Incremental File Reading: Prevents memory overflow; segments constructed dynamically as window space becomes available.
-
Real-time Logging: Provides protocol debugging insights; logs written immediately rather than buffered.
.
├── sender.py # Sender implementation with PLC module
├── receiver.py # Receiver implementation
├── README.md # This file
└── (generated at runtime)
├── sender_log.txt # Sender event log and statistics
└── receiver_log.txt # Receiver event log and statistics
- Kurose & Ross: Computer Networking: A Top-Down Approach (7th/8th edition) - Sections 3.4-3.5.6
- CRC-16 Implementation: https://www.askpython.com/python/examples/crc-16-bit-manual-calculation
- Python Socket Programming: Python standard library
socket,threading,queuemodules - IEEE 802.3 CRC specification