TCP vs UDP — khi nào bỏ độ tin cậy đổi tốc độ
UDP gửi-và-quên, header chỉ 8 byte, không bắt tay — DNS, VoIP, game chọn nó vì trễ chết người hơn mất gói. QUIC xây lại reliability trên UDP để kiểm soát ở user-space.
TL;DR: UDP (User Datagram Protocol — RFC 768) là giao thức "gửi-và-quên": không handshake, không ACK, không đảm bảo thứ tự, không congestion control — header chỉ 8 byte so với 20 byte của TCP. Sự khác biệt cốt lõi là tradeoff: TCP đảm bảo mọi byte tới đủ và đúng thứ tự nhưng tốn RTT cho bắt tay và retransmission khi mất gói; UDP không đảm bảo gì nhưng byte đến đích ngay lập tức hoặc không bao giờ, không bị giữ lại chờ retransmit. DNS, VoIP, game realtime chọn UDP vì mất một gói nhỏ chấp nhận được, còn trễ thì không. QUIC (RFC 9000) — nền của HTTP/3 — xây lại reliability và congestion control ngay trên UDP để kiểm soát ở user-space, tránh phụ thuộc vào TCP trong kernel.
Bạn đã hiểu TCP cung cấp những đảm bảo gì (bài 01 và 02). Bài này hỏi câu ngược: khi nào những đảm bảo đó là gánh nặng thay vì lợi ích?
1. Analogy — Bưu kiện đảm bảo vs tờ rơi
Hình dung bạn cần gửi thứ gì đó:
- Gửi bưu kiện có bảo đảm (TCP): bưu điện ghi nhận từng kiện, yêu cầu người nhận ký xác nhận, gửi lại nếu không nhận được. Hoàn hảo cho hợp đồng pháp lý. Nhưng mỗi bước tốn thời gian — nếu bạn cần thông tin đến tay 1 000 người trong 1 giây, đây là sai lựa chọn.
- Rải tờ rơi từ máy bay (UDP): tờ rơi bay về các hướng, một số rơi xuống đúng đích, một số bay đi — không ai theo dõi hay gửi lại. Nhưng 1 000 tờ rơi phát trong 1 giây. Ổn thôi nếu nội dung từng tờ không quan trọng bằng việc thông tin đến ngay.
| Bưu kiện / tờ rơi | TCP / UDP |
|---|---|
| Ký nhận, gửi lại nếu thất lạc | ACK + retransmission |
| Tốn thời gian chờ xác nhận | 1 RTT handshake + RTT mỗi lần retransmit |
| Tờ rơi mất một tờ — không sao | Mất 1 gói UDP — ứng dụng tự quyết xử lý |
| Tờ rơi đến ngay, không chờ | Byte UDP đến đích trong một lần, không xếp hàng |
TCP = đảm bảo có giá. UDP = nhanh không đảm bảo. Chọn TCP khi dữ liệu không thể thiếu; chọn UDP khi dữ liệu cũ hơn là vô dụng.
2. Header UDP — 8 byte, không hơn
UDP (User Datagram Protocol) được định nghĩa trong RFC 768 (1980) — chỉ 3 trang. Header chỉ có 4 trường:
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| Source Port | Destination Port|
+--------+--------+--------+--------+
| Length | Checksum |
+--------+--------+--------+--------+
| data octets ...
- Source Port / Destination Port (mỗi cái 16-bit): xác định ứng dụng gửi/nhận — giống TCP.
- Length (16-bit): tổng độ dài UDP header + data.
- Checksum (16-bit): kiểm tra lỗi cơ bản (tuỳ chọn với IPv4, bắt buộc với IPv6).
Tổng cộng: 8 byte. So với TCP tối thiểu 20 byte (chưa kể TCP options). Với gói DNS nhỏ (~60 byte data), overhead TCP cao hơn 160% so với UDP.
3. Vì sao TCP gây hại cho realtime — head-of-line blocking
Đây là cơ chế ít được giải thích nhưng quan trọng nhất để hiểu tại sao game/VoIP không thể dùng TCP.
TCP đảm bảo thứ tự byte. Nếu gói thứ 5 bị mất, TCP giữ lại gói thứ 6, 7, 8... chờ gói 5 được retransmit thành công rồi mới giao cho ứng dụng — dù ứng dụng đã nhận được 6, 7, 8. Hiện tượng này gọi là head-of-line blocking (HOL blocking — một gói mất chặn cả hàng sau).
Với stream video:
- Frame 100 bị mất → TCP block frame 101, 102, 103...
- Retransmission mất 1 RTT (50-150ms xuyên lục địa)
- Khi frame 100 đến thì frame 101 đã lỗi thời 150ms
- Người xem thấy video đứng hình rồi giật cục — tệ hơn bỏ luôn frame 100
Với UDP:
- Frame 100 bị mất → ứng dụng nhận frame 101, 102, 103 ngay
- Ứng dụng hiển thị frame 101 (bỏ qua 100) — người xem thấy 1 frame giật nhẹ
- Tốt hơn nhiều về trải nghiệm
sequenceDiagram
participant S as Server
participant N as Mang (co mat goi)
participant C as Client app
Note over S,C: TCP — HOL blocking
S->>N: Frame 100
S->>N: Frame 101
N--xC: Frame 100 (mat)
Note over C: Giu 101, cho 100
S->>N: Retransmit Frame 100
N-->>C: Frame 100 (tre 1 RTT)
Note over C: Giao 100+101 (da cu)
Note over S,C: UDP — khong block
S->>C: Frame 100
S->>C: Frame 101
Note over C: 100 mat, giao 101 ngay4. Use case thực tế — ai chọn giao thức nào và vì sao
5. Cây quyết định chọn giao thức
flowchart TD
A["Du lieu co the mat khong?"] -->|"KHONG — phai den du"| B["Dung TCP"]
A -->|"CO — mat it van ok"| C["Thu tu quan trong?"]
C -->|"KHONG"| D["Tre quan trong hon mat goi?"]
C -->|"CO"| E["Su kien quan trong (game, VoIP signal)"]
E --> F["UDP + tu xu ly thu tu / ACK rieng"]
D -->|"CO — realtime"| G["UDP (VoIP, game state, DNS)"]
D -->|"KHONG"| H["Xem xet TCP hoac UDP + application retry"]
B --> I["File transfer, HTTP, database, email"]
G --> J["Ung dung tu xu ly mat goi neu can"]Heuristic đơn giản:
| Đặc điểm dữ liệu | Chọn |
|---|---|
| Phải đến đủ, đúng thứ tự | TCP |
| Realtime, trễ chết người hơn mất | UDP |
| Nhỏ, 1 round-trip (query/response) | UDP |
| Cần reliability + nhiều stream độc lập | QUIC (UDP) |
| Không biết → mặc định | TCP |
6. QUIC — xây lại reliability trên UDP
QUIC (Quick UDP Internet Connections, RFC 9000, 2021) là giao thức nền của HTTP/3. Thay vì dùng TCP, QUIC xây trên UDP và tự xây các tính năng của TCP ở user-space.
Vì sao không dùng TCP thẳng cho HTTP/2? HTTP/2 multiplex nhiều HTTP request vào 1 TCP connection, nhưng nếu 1 gói TCP bị mất, tất cả stream bị block (HOL blocking ở tầng TCP). QUIC xử lý từng stream độc lập — mất gói ở stream A không chặn stream B.
Vì sao xây trên UDP, không phải giao thức mới hoàn toàn? Vì:
- Firewall và middlebox đã sẵn sàng cho UDP port 443 — giao thức mới ở tầng 4 sẽ bị block.
- Cập nhật không cần thay kernel — QUIC chạy trong user-space (trong app hoặc TLS library), có thể phát hành phiên bản mới như cập nhật phần mềm thường.
QUIC tự xây: connection establishment (0-RTT/1-RTT), reliable delivery per-stream, congestion control (CUBIC/BBR), mã hoá bắt buộc (TLS 1.3 tích hợp). Nói "HTTP/3 dùng UDP" không sai, nhưng QUIC là một giao thức phức tạp chạy trên UDP — không phải "bỏ đảm bảo đi". HTTP/3 và QUIC sẽ được mổ kỹ ở module 2.
7. Pitfall — hiểu nhầm thường gặp
❌ Nhầm 1: "UDP không tin cậy nghĩa là không nên dùng trong production." ✅ UDP là lựa chọn đúng đắn cho các use case phù hợp. DNS — backbone của Internet — chạy trên UDP. Mọi video call, game online đang hoạt động đều dùng UDP. "Không tin cậy" nghĩa là giao thức không tự retransmit — ứng dụng quyết định có cần retry không và retry như thế nào.
❌ Nhầm 2: "Dùng TCP cho streaming video là an toàn hơn vì đảm bảo mọi frame đến đích." ✅ Với video streaming live (WebRTC, RTSP), TCP gây ra trải nghiệm tệ hơn do HOL blocking và buffer bloat — frame cũ đến muộn làm video giật cục. Frame mất còn tốt hơn frame trễ. Video on-demand (YouTube, Netflix adaptive streaming) thì khác — buffer đủ lớn nên TCP ổn.
❌ Nhầm 3: "UDP không có checksum nên dữ liệu có thể sai mà không biết." ✅ UDP có trường Checksum 16-bit trong header. Với IPv6 checksum bắt buộc; với IPv4 tuỳ chọn nhưng hầu hết stack mạng bật mặc định. Điều UDP không làm là retransmit khi detect lỗi — nó chỉ drop gói lỗi và thông báo (hoặc không thông báo) cho ứng dụng. Lớp application có thể tự thêm mã sửa lỗi (FEC) nếu cần.
8. Liên hệ các bài khác
- Bài 01 — TCP 3-way handshake: handshake 3 bước là chi phí cố định của TCP — bài đó giải thích vì sao cần 1 RTT trước khi gửi byte đầu. UDP không có chi phí này.
- Bài 02 — TCP reliability: sequence number, ACK, retransmission là những thứ UDP không có — đọc để hiểu rõ bạn đang bỏ gì khi chọn UDP.
- Bài 03 — TCP flow & congestion control: congestion control (slow start, AIMD) là thứ UDP cũng không có — game/VoIP trên UDP phải tự xử lý hoặc chấp nhận là aggressive.
- Module 2 bài 05 — HTTP/3 & QUIC: QUIC được đề cập ở đây như "reliability trên UDP" — module 2 mổ kỹ cách QUIC thực sự hoạt động, 0-RTT connection, multiplexing per-stream.
9. 📚 Deep Dive — tài liệu gốc
Đọc khi muốn đi tới gốc:
- RFC 768 — User Datagram Protocol — 3 trang, định nghĩa đầy đủ UDP. Đọc được trong 5 phút. Là ví dụ hoàn hảo về thiết kế tối giản.
- RFC 9000 — QUIC: A UDP-Based Multiplexed and Secure Transport — spec đầy đủ của QUIC. Dài (~150 trang) nhưng mục 1 (Introduction) và mục 2 (Design and Rationale) giải thích rõ vì sao chọn UDP và QUIC giải quyết vấn đề gì của TCP.
- RFC 3550 — RTP: A Transport Protocol for Real-Time Applications — giao thức chạy trên UDP cho audio/video realtime, ví dụ điển hình về application-level reliability.
10. Tóm tắt
- UDP (RFC 768) là giao thức "gửi-và-quên": không handshake, không ACK, không thứ tự đảm bảo, không congestion control — header chỉ 8 byte.
- Đánh đổi cốt lõi: UDP không trễ vì retransmission; TCP không mất dữ liệu nhưng tốn RTT cho handshake và block khi có gói mất (HOL blocking).
- HOL blocking là lý do TCP không phù hợp cho realtime: mất 1 gói block tất cả gói sau cho tới khi retransmit xong.
- Use case UDP: DNS (query nhỏ, 1 RTT), VoIP/video (mất frame chấp nhận, trễ không), game realtime (state cũ vô dụng), DHCP (chưa có IP).
- QUIC (RFC 9000) xây reliability + congestion control trên UDP ở user-space, giải quyết HOL blocking của TCP — nền tảng của HTTP/3.
- Chọn TCP khi dữ liệu phải đến đủ; chọn UDP khi dữ liệu cũ hơn là vô dụng hoặc latency quan trọng hơn completeness.
11. Tự kiểm tra
Q1Vì sao header UDP chỉ có 8 byte trong khi TCP tối thiểu 20 byte?▸
Q2HOL blocking là gì và vì sao nó làm TCP không phù hợp cho VoIP?▸
Q3DNS query dùng UDP thay vì TCP. Vì sao điều này hợp lý?▸
Q4QUIC chạy trên UDP nhưng vẫn có reliability. Điều này không mâu thuẫn sao? Vì sao không dùng TCP thẳng?▸
Q5Game FPS gửi vị trí nhân vật 60 lần/giây qua UDP. Vì sao không dùng TCP cho chắc ăn?▸
Q6Bạn cần chọn giao thức cho một hệ thống telemetry gửi metrics từ 10 000 sensor mỗi giây. Metrics có thể mất vài điểm nhưng không cần exact ordering. Chọn gì và vì sao?▸
Q7Vì sao DHCP phải dùng UDP thay vì TCP?▸
255.255.255.255) từ địa chỉ nguồn 0.0.0.0 — cơ chế duy nhất hoạt động được trước khi client có địa chỉ. Đây là ví dụ UDP là lựa chọn duy nhất, không phải chỉ là lựa chọn tốt hơn.Bài tiếp theo: Connection pooling & keep-alive — vì sao app cần pool
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên