TCP vs UDP — Network Protocol Guide - MarekBykowski/readme GitHub Wiki
Quick Summary
| Property | TCP | UDP |
|---|---|---|
| Connection | connection-oriented (3-way handshake) | connectionless (just send) |
| Reliability | guaranteed delivery, every byte | best effort — may drop |
| Ordering | always in order | may arrive out of order |
| Retransmission | yes — on timeout/loss | none |
| Flow control | yes — window size | none |
| Congestion control | yes — CUBIC, BBR, Reno | none |
| Header size | 20–60 bytes | 8 bytes only |
| State | stateful (seq, ack, window) | stateless |
| Latency | higher | minimal |
| Head-of-line blocking | yes — stalls on packet loss | no |
| Drone use | firmware upload, config, logs | telemetry, MAVLink, video |
| MAVLink port | — | 14550 (GCS), 14540 (MAVSDK) |
TCP — 3-Way Handshake
CLIENT SERVER
│ │
│ ──── SYN (seq=100) ─────────► │ "I want to connect"
│ │
│ ◄─── SYN-ACK (seq=200,ack=101)│ "OK, I'm ready"
│ │
│ ──── ACK (ack=201) ─────────► │ "acknowledged"
│ │
│ ════════ DATA FLOWS ═════════ │
│ │
│ ──── FIN ───────────────────► │ "I'm done"
│ ◄─── FIN-ACK ─────────────── │
│ ──── ACK ───────────────────► │
│ │
CLOSED
Why 3 steps? Both sides must agree on starting sequence numbers. SYN = synchronise. Without this, there's no way to detect lost or reordered packets.
TCP — Retransmission and Head-of-Line Blocking
SENDER RECEIVER
│ │
│ ──── seq=1 ────────────────► │ ✓ received
│ ◄─── ACK=2 ──────────────── │
│ │
│ ──── seq=2 ────────────────► │ ✗ LOST
│ │
│ ... timeout 200ms ... │
│ │
│ ──── seq=3 ────────────────► │ buffered — not delivered yet!
│ ──── seq=4 ────────────────► │ buffered — not delivered yet!
│ │
│ ──── seq=2 (RETRANSMIT) ───► │ ✓ received
│ ◄─── ACK=5 ──────────────── │ seq 2,3,4 all delivered in order
⚠️ Head-of-line blocking: seq=3 and seq=4 arrive but are held back until seq=2 is retransmitted. All subsequent packets stall. Fatal for real-time telemetry.
TCP State Machine
CLOSED
│ send SYN
▼
SYN_SENT
│ recv SYN-ACK, send ACK
▼
ESTABLISHED ◄─── data flows here
│ send FIN
▼
FIN_WAIT_1
│ recv FIN-ACK
▼
FIN_WAIT_2
│ recv FIN
▼
TIME_WAIT ──── 2×MSL timeout (~60s) ────► CLOSED
💡 TIME_WAIT: waits to ensure remote end received final ACK. Prevents old packets from corrupting new connections on the same port.
TCP Header
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
┌─────────────────────────────┬─────────────────────────────────┐
│ Source Port │ Destination Port │
├─────────────────────────────┴─────────────────────────────────┤
│ Sequence Number │
├───────────────────────────────────────────────────────────────┤
│ Acknowledgment Number │
├────────┬───────┬─┬─┬─┬─┬─┬─┬───────────────────────────────┤
│ Offset │ Res │U│A│P│R│S│F│ Window Size │
│ │ │R│C│S│S│Y│I│ │
├────────┴───────┴─┴─┴─┴─┴─┴─┴───────────────────────────────┤
│ Checksum │ Urgent Pointer │
└───────────────────────────────┴───────────────────────────────┘
Minimum: 20 bytes
UDP — Fire and Forget
SENDER RECEIVER
│ │
│ ──── dgram #1 (t=0ms) ─────► │ ✓ received — delivered immediately
│ ──── dgram #2 (t=100ms) ───► │ ✗ lost — gone, no retransmit
│ ──── dgram #3 (t=200ms) ───► │ ✓ received — delivered immediately
│ ──── dgram #4 (t=300ms) ───► │ ✓ received — delivered immediately
│ │
Packet #2 is lost — #3 and #4 are delivered immediately with no stall. Latency unaffected by loss. This is why MAVLink uses UDP.
UDP Header
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
┌─────────────────────────────┬─────────────────────────────────┐
│ Source Port │ Destination Port │
├─────────────────────────────┼─────────────────────────────────┤
│ Length │ Checksum │
├─────────────────────────────┴─────────────────────────────────┤
│ Data │
└───────────────────────────────────────────────────────────────┘
Header: 8 bytes only — 4 fields, no state, no seq numbers
MAVLink over UDP
FLIGHT CONTROLLER GCS / COMPANION COMPUTER
│ │
│ ── HEARTBEAT (1Hz) ─────────► │ sysid=1, compid=1
│ ── HEARTBEAT (1Hz) ─────────► │ "I'm alive"
│ │
│ ── GLOBAL_POSITION (10Hz) ──► │ lat, lon, alt, heading
│ ── ATTITUDE (10Hz) ─────────► │ roll, pitch, yaw
│ ── SYS_STATUS (1Hz) ────────► │ battery, sensors
│ │
│ ◄── COMMAND_LONG ─────────── │ MAV_CMD_NAV_TAKEOFF
│ ── COMMAND_ACK ─────────────► │ result=ACCEPTED
│ │
Standard ports:
| Port | Use |
|---|---|
14550 |
GCS (QGroundControl, Mission Planner) |
14540 |
MAVSDK / offboard control |
14580 |
MAVLink router |
Why UDP Beats TCP for Drone Telemetry
TCP — retransmit stalls everything:
t=0ms pos ──────────────────────► ✓
t=100ms pos ──────────────────────► ✗ LOST
t=200ms pos (BLOCKED — waiting) ⊘
t=300ms pos (BLOCKED — waiting) ⊘
t=400ms retransmit t=100ms ────────► ✓ but 300ms stale!
t=400ms pos t=200ms ───────────────► ✓ but still delayed
UDP — drop and move on:
t=0ms pos ──────────────────────► ✓ fresh
t=100ms pos ──────────────────────► ✗ dropped, forgotten
t=200ms pos ──────────────────────► ✓ fresh, no stall
t=300ms pos ──────────────────────► ✓ fresh
⚠️ Stale telemetry = wrong control decisions. A dropped packet is better than a 300ms delayed packet. MAVLink includes its own sequence number (
seqfield in header) to detect drops at the application layer — no TCP needed.
When TCP Wins over UDP
FIRMWARE UPLOAD — reliability critical, latency irrelevant:
SENDER RECEIVER
│ │
│ ──── chunk #1 (0-1023B) ───► │ ✓ ACK
│ ──── chunk #2 (1024-2047B) ► │ ✗ LOST
│ ──── chunk #2 (RETRANSMIT) ► │ ✓ ACK
│ ──── chunk #3 (2048-3071B) ► │ ✓ ACK
│ │
Use TCP for:
- Firmware upload — corruption = crashed drone
- Parameter get/set — must not corrupt
- Log file download — integrity required
- SSH to companion computer
Use UDP for:
- MAVLink telemetry — latency critical
- Video streaming — stale frame worse than dropped frame
- Position/attitude at 10–50Hz — freshness beats reliability
Drone Network Stack (OSI layers)
L7 Application MAVLink, MAVSDK, ROS2, HTTP (config)
L6 Presentation (absorbed into application in practice)
L5 Session (absorbed into application in practice)
─────────────────────────────────────────────────────────
L4 Transport UDP (telemetry) / TCP (firmware, SSH)
─────────────────────────────────────────────────────────
L3 Network IP (192.168.x.x), ICMP
─────────────────────────────────────────────────────────
L2 Data Link WiFi 802.11 (companion ↔ GCS)
900MHz radio link (telemetry, long range)
Ethernet (bench testing)
─────────────────────────────────────────────────────────
L1 Physical RF signal, antenna
2.4 / 5.8 GHz (WiFi, RC control)
868 / 915 MHz (telemetry radio, long range)
Generated during prep session · Swarmer Integration Engineer · 2026