%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#E67E22', 'secondaryColor': '#16A085', 'tertiaryColor': '#E8F6F3', 'fontSize': '14px'}}}%%
graph LR
subgraph ESP32["ESP32 DevKit"]
GPIO2["GPIO 2"]
GPIO4["GPIO 4"]
GPIO5["GPIO 5"]
GPIO18["GPIO 18"]
GND["GND"]
end
subgraph LEDs["Transport State Indicators"]
GREEN["Green LED<br/>(ACK Received)"]
RED["Red LED<br/>(NACK/Timeout)"]
YELLOW["Yellow LED<br/>(Transmitting)"]
BLUE["Blue LED<br/>(Msg Received)"]
end
GPIO4 -->|"220 ohm"| GREEN
GPIO2 -->|"220 ohm"| RED
GPIO5 -->|"220 ohm"| YELLOW
GPIO18 -->|"220 ohm"| BLUE
GREEN --> GND
RED --> GND
YELLOW --> GND
BLUE --> GND
style ESP32 fill:#2C3E50,stroke:#16A085,color:#fff
style LEDs fill:#E8F6F3,stroke:#16A085,color:#2C3E50
style GREEN fill:#2ECC71,stroke:#27AE60,color:#fff
style RED fill:#E74C3C,stroke:#C0392B,color:#fff
style YELLOW fill:#F1C40F,stroke:#F39C12,color:#2C3E50
style BLUE fill:#3498DB,stroke:#2980B9,color:#fff
741 Transport Protocols: Hands-On Lab
741.1 Learning Objectives
By the end of this lab, you will be able to:
- Implement message sequencing: Use sequence numbers to detect missing, duplicate, and out-of-order messages
- Build an acknowledgment system: Create ACK/NACK responses to confirm or reject message delivery
- Design timeout and retry logic: Handle message loss with configurable timeouts and exponential backoff
- Analyze transport layer statistics: Calculate throughput, loss rate, and retransmission overhead in real-time
741.2 Lab: Build a Reliable Message Transport System
This hands-on lab demonstrates core transport layer concepts by building a reliable message delivery system on an ESP32. You will implement the fundamental mechanisms that make protocols like TCP reliable: sequence numbers, acknowledgments, timeouts, and retransmissions.
741.2.1 Components Needed
| Component | Quantity | Purpose |
|---|---|---|
| ESP32 DevKit | 1 | Microcontroller simulating sender and receiver |
| Green LED | 1 | ACK received indicator |
| Red LED | 1 | NACK/Timeout indicator |
| Yellow LED | 1 | Transmission in progress |
| Blue LED | 1 | Message received |
| 220 ohm Resistors | 4 | Current limiting for LEDs |
| Breadboard | 1 | Circuit assembly |
| Jumper Wires | Several | Connections |
741.2.2 Wokwi Simulator
Use the embedded simulator below to build and test your reliable transport system. Click βStart Simulationβ to begin.
741.2.3 Circuit Diagram
741.2.4 Complete Code
Copy this code into the Wokwi editor and upload to the ESP32:
/*
* Reliable Message Transport System for ESP32
*
* This program demonstrates core transport layer concepts:
* - Message sequencing with sequence numbers
* - Acknowledgment system (ACK/NACK)
* - Timeout and retry mechanism with exponential backoff
* - Simulated packet loss for testing reliability
* - Real-time throughput and loss statistics
*
* LED Indicators:
* - Green (GPIO 4): ACK received - message delivered successfully
* - Red (GPIO 2): NACK/Timeout - message delivery failed
* - Yellow (GPIO 5): Transmitting - message in transit
* - Blue (GPIO 18): Received - new message arrived
*
* Transport Layer Concepts Demonstrated:
* 1. Sequence Numbers: Each message has a unique ID for ordering
* 2. Acknowledgments: Receiver confirms each message
* 3. Timeouts: Sender waits limited time for ACK
* 4. Retransmission: Failed messages are resent
* 5. Statistics: Track throughput and reliability
*/
// ============= PIN DEFINITIONS =============
#define LED_ACK 4 // Green LED - ACK received
#define LED_NACK 2 // Red LED - NACK/Timeout
#define LED_TRANSMIT 5 // Yellow LED - Transmission in progress
#define LED_RECEIVED 18 // Blue LED - Message received
// ============= TRANSPORT CONFIGURATION =============
#define INITIAL_TIMEOUT_MS 500 // Initial timeout for ACK (milliseconds)
#define MAX_TIMEOUT_MS 4000 // Maximum timeout after backoff
#define MAX_RETRIES 3 // Maximum retransmission attempts
#define PACKET_LOSS_PERCENT 20 // Simulated packet loss rate (0-100)
#define WINDOW_SIZE 1 // Stop-and-wait (1), increase for sliding window
// ============= MESSAGE TYPES =============
#define MSG_DATA 0x01 // Data message
#define MSG_ACK 0x02 // Positive acknowledgment
#define MSG_NACK 0x03 // Negative acknowledgment (request retransmit)
// ============= MESSAGE STRUCTURE =============
struct TransportMessage {
uint8_t type; // MSG_DATA, MSG_ACK, or MSG_NACK
uint16_t sequenceNum; // Sequence number (0-65535)
uint16_t ackNum; // Acknowledgment number (for ACK/NACK)
uint8_t payloadLen; // Length of payload
char payload[64]; // Message payload
uint16_t checksum; // Simple checksum for integrity
};
// ============= STATISTICS TRACKING =============
struct TransportStats {
uint32_t messagesSent;
uint32_t messagesReceived;
uint32_t acksReceived;
uint32_t nacksReceived;
uint32_t timeouts;
uint32_t retransmissions;
uint32_t bytesTransmitted;
uint32_t simulatedDrops;
unsigned long startTime;
};
// ============= GLOBAL VARIABLES =============
uint16_t nextSequenceNum = 0; // Next sequence number to use
uint16_t expectedSequenceNum = 0; // Expected sequence number (receiver)
TransportStats stats;
bool verboseMode = true; // Print detailed logs
// ============= FUNCTION PROTOTYPES =============
void initializeLEDs();
void setLED(int led, bool state);
void blinkLED(int led, int times, int delayMs);
uint16_t calculateChecksum(TransportMessage* msg);
bool verifyChecksum(TransportMessage* msg);
void createDataMessage(TransportMessage* msg, const char* data);
void createAckMessage(TransportMessage* ack, uint16_t ackNum);
void createNackMessage(TransportMessage* nack, uint16_t nackNum);
bool simulatePacketLoss();
bool sendWithReliability(const char* data);
void processReceivedMessage(TransportMessage* msg);
void printMessage(TransportMessage* msg, const char* direction);
void printStatistics();
float calculateThroughput();
// ============= SETUP =============
void setup() {
Serial.begin(115200);
delay(1000);
// Initialize random seed for packet loss simulation
randomSeed(analogRead(0));
// Initialize LEDs
initializeLEDs();
// Initialize statistics
memset(&stats, 0, sizeof(TransportStats));
stats.startTime = millis();
// Startup sequence
Serial.println("\n");
Serial.println("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ");
Serial.println("β RELIABLE MESSAGE TRANSPORT SYSTEM - ESP32 LAB β");
Serial.println("β β");
Serial.println("β Demonstrating Transport Layer Concepts: β");
Serial.println("β - Sequence Numbers - Acknowledgments β");
Serial.println("β - Timeouts/Retries - Packet Loss Handling β");
Serial.println("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ");
Serial.println();
// Show configuration
Serial.println("=== CONFIGURATION ===");
Serial.printf("Initial Timeout: %d ms\n", INITIAL_TIMEOUT_MS);
Serial.printf("Max Timeout: %d ms\n", MAX_TIMEOUT_MS);
Serial.printf("Max Retries: %d\n", MAX_RETRIES);
Serial.printf("Packet Loss Rate: %d%%\n", PACKET_LOSS_PERCENT);
Serial.printf("Window Size: %d (Stop-and-Wait)\n", WINDOW_SIZE);
Serial.println();
// LED test
Serial.println("=== LED TEST ===");
Serial.println("Testing all LEDs...");
blinkLED(LED_ACK, 2, 200);
blinkLED(LED_NACK, 2, 200);
blinkLED(LED_TRANSMIT, 2, 200);
blinkLED(LED_RECEIVED, 2, 200);
Serial.println("LED test complete.\n");
delay(1000);
}
// ============= MAIN LOOP =============
void loop() {
// Demonstrate reliable message transmission
static int messageCount = 0;
char messageBuffer[64];
// Create a test message
snprintf(messageBuffer, sizeof(messageBuffer),
"Sensor reading #%d: Temp=%.1fC",
messageCount, 20.0 + (random(100) / 10.0));
Serial.println("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ");
Serial.printf(">>> SENDING MESSAGE %d <<<\n", messageCount);
Serial.println("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ");
// Send with reliability (handles retries, timeouts, etc.)
bool success = sendWithReliability(messageBuffer);
if (success) {
Serial.println("Result: MESSAGE DELIVERED SUCCESSFULLY");
} else {
Serial.println("Result: MESSAGE DELIVERY FAILED (max retries exceeded)");
}
// Print statistics every 5 messages
if (messageCount % 5 == 4) {
printStatistics();
}
messageCount++;
Serial.println();
// Wait before next transmission
delay(3000);
}
// ============= LED FUNCTIONS =============
void initializeLEDs() {
pinMode(LED_ACK, OUTPUT);
pinMode(LED_NACK, OUTPUT);
pinMode(LED_TRANSMIT, OUTPUT);
pinMode(LED_RECEIVED, OUTPUT);
// All LEDs off initially
digitalWrite(LED_ACK, LOW);
digitalWrite(LED_NACK, LOW);
digitalWrite(LED_TRANSMIT, LOW);
digitalWrite(LED_RECEIVED, LOW);
}
void setLED(int led, bool state) {
digitalWrite(led, state ? HIGH : LOW);
}
void blinkLED(int led, int times, int delayMs) {
for (int i = 0; i < times; i++) {
digitalWrite(led, HIGH);
delay(delayMs);
digitalWrite(led, LOW);
delay(delayMs);
}
}
// ============= CHECKSUM FUNCTIONS =============
uint16_t calculateChecksum(TransportMessage* msg) {
uint16_t sum = 0;
sum += msg->type;
sum += msg->sequenceNum;
sum += msg->ackNum;
sum += msg->payloadLen;
for (int i = 0; i < msg->payloadLen; i++) {
sum += (uint8_t)msg->payload[i];
}
return ~sum; // One's complement
}
bool verifyChecksum(TransportMessage* msg) {
uint16_t expected = calculateChecksum(msg);
return (msg->checksum == expected);
}
// ============= MESSAGE CREATION =============
void createDataMessage(TransportMessage* msg, const char* data) {
msg->type = MSG_DATA;
msg->sequenceNum = nextSequenceNum;
msg->ackNum = 0;
msg->payloadLen = strlen(data);
if (msg->payloadLen > 63) msg->payloadLen = 63;
strncpy(msg->payload, data, msg->payloadLen);
msg->payload[msg->payloadLen] = '\0';
msg->checksum = calculateChecksum(msg);
}
void createAckMessage(TransportMessage* ack, uint16_t ackNum) {
ack->type = MSG_ACK;
ack->sequenceNum = 0;
ack->ackNum = ackNum;
ack->payloadLen = 0;
ack->payload[0] = '\0';
ack->checksum = calculateChecksum(ack);
}
void createNackMessage(TransportMessage* nack, uint16_t nackNum) {
nack->type = MSG_NACK;
nack->sequenceNum = 0;
nack->ackNum = nackNum;
nack->payloadLen = 0;
nack->payload[0] = '\0';
nack->checksum = calculateChecksum(nack);
}
// ============= PACKET LOSS SIMULATION =============
bool simulatePacketLoss() {
int roll = random(100);
bool lost = (roll < PACKET_LOSS_PERCENT);
if (lost) {
stats.simulatedDrops++;
if (verboseMode) {
Serial.printf(" [SIMULATED] Packet lost! (roll=%d < %d%%)\n",
roll, PACKET_LOSS_PERCENT);
}
}
return lost;
}
// ============= RELIABLE SEND WITH RETRIES =============
bool sendWithReliability(const char* data) {
TransportMessage msg;
TransportMessage response;
int retryCount = 0;
int currentTimeout = INITIAL_TIMEOUT_MS;
// Create the data message
createDataMessage(&msg, data);
printMessage(&msg, "SEND");
while (retryCount <= MAX_RETRIES) {
// Turn on transmit LED
setLED(LED_TRANSMIT, true);
if (verboseMode) {
if (retryCount > 0) {
Serial.printf("\n--- RETRY %d/%d (timeout=%dms) ---\n",
retryCount, MAX_RETRIES, currentTimeout);
stats.retransmissions++;
}
Serial.printf(" [TX] Sending SEQ=%d, waiting for ACK...\n",
msg.sequenceNum);
}
stats.messagesSent++;
stats.bytesTransmitted += sizeof(TransportMessage);
// Simulate network transmission delay
delay(50);
// Turn off transmit LED
setLED(LED_TRANSMIT, false);
// Simulate the "receiver" processing
// Check if packet was "lost" in transit
if (simulatePacketLoss()) {
// Packet lost - wait for timeout
if (verboseMode) {
Serial.printf(" [WAIT] Waiting %dms for ACK (packet was lost)...\n",
currentTimeout);
}
delay(currentTimeout);
// Timeout occurred
setLED(LED_NACK, true);
delay(200);
setLED(LED_NACK, false);
stats.timeouts++;
if (verboseMode) {
Serial.println(" [TIMEOUT] No ACK received - will retry");
}
// Exponential backoff
retryCount++;
currentTimeout = min(currentTimeout * 2, MAX_TIMEOUT_MS);
continue;
}
// Packet arrived at receiver
setLED(LED_RECEIVED, true);
stats.messagesReceived++;
if (verboseMode) {
Serial.printf(" [RX] Message received at destination\n");
}
// Receiver processes message and sends ACK
processReceivedMessage(&msg);
// Simulate receiver creating ACK
// Small chance of ACK being lost too
if (simulatePacketLoss()) {
setLED(LED_RECEIVED, false);
if (verboseMode) {
Serial.println(" [SIMULATED] ACK was lost in transit!");
Serial.printf(" [WAIT] Waiting %dms for ACK...\n", currentTimeout);
}
delay(currentTimeout);
setLED(LED_NACK, true);
delay(200);
setLED(LED_NACK, false);
stats.timeouts++;
retryCount++;
currentTimeout = min(currentTimeout * 2, MAX_TIMEOUT_MS);
continue;
}
// ACK received successfully
createAckMessage(&response, msg.sequenceNum);
printMessage(&response, "RECV");
setLED(LED_RECEIVED, false);
setLED(LED_ACK, true);
stats.acksReceived++;
if (verboseMode) {
Serial.printf(" [ACK] Received ACK for SEQ=%d\n", response.ackNum);
}
delay(300);
setLED(LED_ACK, false);
// Success! Increment sequence number for next message
nextSequenceNum++;
return true;
}
// Max retries exceeded
Serial.println(" [FAIL] Max retries exceeded!");
blinkLED(LED_NACK, 3, 150);
return false;
}
// ============= RECEIVER MESSAGE PROCESSING =============
void processReceivedMessage(TransportMessage* msg) {
if (verboseMode) {
// Check sequence number
if (msg->sequenceNum == expectedSequenceNum) {
Serial.printf(" [RX] Sequence OK (expected=%d, got=%d)\n",
expectedSequenceNum, msg->sequenceNum);
expectedSequenceNum++;
} else if (msg->sequenceNum < expectedSequenceNum) {
Serial.printf(" [RX] DUPLICATE detected (expected=%d, got=%d)\n",
expectedSequenceNum, msg->sequenceNum);
} else {
Serial.printf(" [RX] OUT OF ORDER (expected=%d, got=%d)\n",
expectedSequenceNum, msg->sequenceNum);
}
// Verify checksum
if (verifyChecksum(msg)) {
Serial.println(" [RX] Checksum verified OK");
} else {
Serial.println(" [RX] CHECKSUM FAILED - would send NACK");
stats.nacksReceived++;
}
}
}
// ============= MESSAGE PRINTING =============
void printMessage(TransportMessage* msg, const char* direction) {
if (!verboseMode) return;
Serial.println();
Serial.printf(" ββββββββββββββββ %s MESSAGE ββββββββββββββββ\n", direction);
Serial.printf(" β Type: %-28s β\n",
msg->type == MSG_DATA ? "DATA" :
msg->type == MSG_ACK ? "ACK" : "NACK");
Serial.printf(" β Sequence: %-28d β\n", msg->sequenceNum);
Serial.printf(" β Ack Number: %-28d β\n", msg->ackNum);
Serial.printf(" β Payload Len: %-28d β\n", msg->payloadLen);
if (msg->payloadLen > 0) {
Serial.printf(" β Payload: %-28s β\n", msg->payload);
}
Serial.printf(" β Checksum: 0x%04X β\n", msg->checksum);
Serial.println(" ββββββββββββββββββββββββββββββββββββββββββββ");
}
// ============= STATISTICS =============
void printStatistics() {
unsigned long elapsed = (millis() - stats.startTime) / 1000;
float throughput = calculateThroughput();
float lossRate = stats.messagesSent > 0 ?
(float)(stats.simulatedDrops * 100) / stats.messagesSent : 0;
float retxRate = stats.messagesSent > 0 ?
(float)(stats.retransmissions * 100) / stats.messagesSent : 0;
Serial.println();
Serial.println("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ");
Serial.println("β TRANSPORT LAYER STATISTICS β");
Serial.println("β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£");
Serial.printf("β Messages Sent: %-10lu β\n",
stats.messagesSent);
Serial.printf("β Messages Received: %-10lu β\n",
stats.messagesReceived);
Serial.printf("β ACKs Received: %-10lu β\n",
stats.acksReceived);
Serial.printf("β Timeouts: %-10lu β\n",
stats.timeouts);
Serial.printf("β Retransmissions: %-10lu β\n",
stats.retransmissions);
Serial.printf("β Simulated Drops: %-10lu β\n",
stats.simulatedDrops);
Serial.println("β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£");
Serial.printf("β Elapsed Time: %-10lu seconds β\n",
elapsed);
Serial.printf("β Throughput: %-10.2f bytes/sec β\n",
throughput);
Serial.printf("β Loss Rate: %-10.1f%% β\n",
lossRate);
Serial.printf("β Retransmission Rate: %-10.1f%% β\n",
retxRate);
Serial.println("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ");
}
float calculateThroughput() {
unsigned long elapsed = millis() - stats.startTime;
if (elapsed == 0) return 0;
return (float)stats.bytesTransmitted / (elapsed / 1000.0);
}741.2.5 Step-by-Step Instructions
Step 1: Set Up the Circuit
- Open the Wokwi simulator above (or visit wokwi.com/projects/new/esp32)
- Add four LEDs to the breadboard (green, red, yellow, blue)
- Connect each LED with a 220 ohm resistor
- Wire the connections as shown in the circuit diagram:
- GPIO 4 to Green LED (ACK indicator)
- GPIO 2 to Red LED (NACK/Timeout indicator)
- GPIO 5 to Yellow LED (Transmitting indicator)
- GPIO 18 to Blue LED (Received indicator)
- All LED cathodes to GND
Step 2: Upload and Run the Code
- Copy the complete code into the Wokwi code editor
- Click βStart Simulationβ to begin
- Open the Serial Monitor (set to 115200 baud) to see detailed output
Step 3: Observe Transport Behavior
Watch the LEDs and Serial Monitor to understand each phase:
| LED | Meaning | Transport Layer Concept |
|---|---|---|
| Yellow ON | Message being transmitted | Data segment in transit |
| Blue ON | Message arrived at receiver | Successful delivery |
| Green ON | ACK received by sender | Acknowledgment mechanism |
| Red ON | Timeout or NACK | Retransmission trigger |
Step 4: Analyze the Statistics
After 5 messages, the system prints statistics. Look for:
- Retransmission Rate: Higher than packet loss rate? Why? (ACK loss doubles retransmissions)
- Throughput: How does packet loss affect effective throughput?
- Timeout Count: Each timeout represents wasted waiting time
741.2.6 Understanding the Code
Key Transport Layer Concepts in the Code:
uint16_t sequenceNum; // Unique ID for each message
uint16_t ackNum; // Which message is being acknowledgedSequence numbers enable: - Ordering: Receiver knows correct order even if packets arrive shuffled - Duplicate detection: Same sequence number = retransmission, not new data - Loss detection: Gap in sequence numbers = missing packet
void createAckMessage(TransportMessage* ack, uint16_t ackNum) {
ack->type = MSG_ACK;
ack->ackNum = ackNum; // "I received message #ackNum"
}ACK/NACK enables: - Confirmation: Sender knows message arrived - Error feedback: NACK requests specific retransmission - Flow control: Receiver controls senderβs pace
int currentTimeout = INITIAL_TIMEOUT_MS; // Start at 500ms
// On timeout:
currentTimeout = min(currentTimeout * 2, MAX_TIMEOUT_MS); // Double itTimeouts handle: - Lost packets: No ACK after timeout triggers retry - Lost ACKs: Sender cannot distinguish from lost data - Exponential backoff: Prevents network congestion during problems
bool simulatePacketLoss() {
return (random(100) < PACKET_LOSS_PERCENT); // 20% default
}Simulating loss helps understand: - Why reliability matters: See real impact of unreliable networks - Overhead cost: Retransmissions consume bandwidth and time - Trade-offs: More aggressive timeouts vs. unnecessary retries
741.2.7 Experiments to Try
Experiment 1: Vary Packet Loss Rate
Change PACKET_LOSS_PERCENT to different values:
| Loss Rate | Expected Behavior |
|---|---|
| 0% | All messages succeed first try |
| 20% | Some retransmissions, most succeed |
| 50% | Many retries, some failures |
| 80% | Most messages fail after max retries |
Experiment 2: Adjust Timeout Values
| Setting | Effect |
|---|---|
| Lower timeout (100ms) | Faster failure detection, but more false retries |
| Higher timeout (2000ms) | Fewer false retries, but slower recovery |
| No backoff | Network stays congested during problems |
Experiment 3: Remove Reliability Features
Comment out different sections to see what breaks: - Remove checksums: Corrupted data goes undetected - Remove sequence numbers: Duplicates and reordering cause chaos - Remove retries: Any packet loss means data loss
741.2.8 Challenge Exercises
Modify the code to send multiple messages before waiting for ACKs:
#define WINDOW_SIZE 4 // Send up to 4 messages before blocking
// Track which messages are awaiting ACK
bool awaitingAck[WINDOW_SIZE];
uint16_t windowBase = 0; // First unacknowledged sequence number
// Send messages until window is full
while (nextSeq < windowBase + WINDOW_SIZE) {
sendMessage(nextSeq++);
}
// On ACK, slide window forward
windowBase = ackNum + 1;Goal: Improve throughput by not waiting for each ACK individually.
Implement basic congestion control that reduces send rate when losses occur:
int congestionWindow = 4; // Start with window of 4
// On successful ACK
if (congestionWindow < MAX_WINDOW) {
congestionWindow++; // Additive increase
}
// On timeout (congestion signal)
congestionWindow = max(1, congestionWindow / 2); // Multiplicative decreaseGoal: Prevent overwhelming the network when congestion is detected.
Instead of retransmitting from the lost packet onward (Go-Back-N), only retransmit the specific lost packets:
// Receiver tracks received packets with bitmap
uint32_t receivedBitmap = 0;
// On receiving packet with seq N
receivedBitmap |= (1 << (N - windowBase));
// Send selective NACK for missing packets
for (int i = 0; i < WINDOW_SIZE; i++) {
if (!(receivedBitmap & (1 << i))) {
sendNack(windowBase + i);
}
}Goal: Reduce retransmission overhead by only resending what was actually lost.
741.2.9 Key Transport Layer Concepts Summary
This lab demonstrates the fundamental mechanisms that make reliable transport possible:
| Concept | What It Solves | How It Works |
|---|---|---|
| Sequence Numbers | Ordering, duplicates, loss detection | Each message gets unique incremental ID |
| Acknowledgments | Delivery confirmation | Receiver sends ACK/NACK for each message |
| Timeouts | Lost packet detection | Sender waits limited time for ACK |
| Retransmission | Lost data recovery | Resend unacknowledged messages |
| Checksums | Data corruption | Mathematical verification of integrity |
| Exponential Backoff | Congestion avoidance | Double timeout on each failure |
The mechanisms in this lab directly map to real transport protocols:
- TCP uses all these mechanisms plus sliding windows, congestion control, and flow control
- QUIC (used by HTTP/3) adds encryption and multiplexing
- MQTT QoS 1 uses sequence numbers and ACKs similar to this lab
- CoAP Confirmable messages use the same timeout/retry approach
Understanding these fundamentals helps you make informed protocol choices for IoT applications.
741.3 Original Source Figures (Alternative Views)

Source: CP IoT System Design Guide, Chapter 4 - Networking Fundamentals

Source: CP IoT System Design Guide, Chapter 4 - Networking Fundamentals

Source: CP IoT System Design Guide, Chapter 4 - Networking Fundamentals

Source: CP IoT System Design Guide, Chapter 4 - Networking Fundamentals
741.4 Summary
This hands-on lab demonstrated the core transport layer mechanisms through practical implementation:
- Sequence numbers enable ordering, duplicate detection, and loss detection
- Acknowledgments confirm delivery and trigger retransmissions when missing
- Timeouts with exponential backoff handle lost packets without overwhelming the network
- Checksums catch data corruption before it causes problems
- Statistics tracking reveals the true cost of reliability overhead
The challenge exercises provide opportunities to implement advanced mechanisms like sliding windows, congestion control, and selective repeat.
741.5 Whatβs Next
Continue your transport protocol learning:
- Transport Selection and Scenarios: Decision frameworks for IoT protocol selection
- Transport Optimizations and Implementation: TCP optimization techniques and lightweight stacks
- CoAP Protocol: See how CoAP applies these concepts over UDP
- MQTT Protocol: Explore TCP-based pub/sub messaging for IoT
Prerequisites (read these first):
- Layered Network Models - Understanding OSI and TCP/IP models is crucial since transport protocols operate at Layer 4
- Networking Basics - Knowledge of packets, headers, and ports provides the foundation for transport protocols
- Networking Fundamentals - Core networking concepts including IP addressing and protocol stacks
See Also:
- CoAP Protocol - Constrained Application Protocol building on UDP for IoT
- MQTT Protocol - Message Queue Telemetry Transport using TCP for pub/sub messaging
- IoT Protocols Overview - Comprehensive comparison of application and transport protocols
- Encryption Architecture - TLS/DTLS in the broader security context