Zoom-in: TCP

Mọi HTTP request đều đi trên TCP. Nhưng trước khi byte đầu tiên của dữ liệu đi qua, đã có 3 gói tin trao đổi mà không mang dữ liệu nào. Đó không phải overhead thừa — đó là giá phải trả để có một kênh truyền đáng tin cậy trên một mạng vốn không đảm bảo điều gì.
Phóng to dần vào đó.
Layer 1 — Vấn đề: Internet không đảm bảo giao hàng
Internet là một mạng best-effort. Mỗi router chỉ cố gắng chuyển tiếp gói tin — không có cam kết, không có xác nhận.
graph LR
C["💻 Client"] -->|"gói 1"| I["🌐 Internet"]
C -->|"gói 2"| I
C -->|"gói 3"| I
I -->|"gói 1 ✓"| S["🖥️ Server"]
I -->|"gói 3 ✓"| S
I -.->|"gói 2 ✗ mất"| S
style C fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
style I fill:#3b2a1a,stroke:#f59e0b,color:#fcd34d
style S fill:#1a3a2a,stroke:#22c55e,color:#86efac
Gói tin có thể mất, đến không đúng thứ tự, hoặc trùng lặp. IP không có cơ chế xử lý những trường hợp này. Tầng trên phải tự lo.
Layer 2 — 3-way handshake: mở kết nối
Trước khi gửi dữ liệu, TCP yêu cầu hai bên thiết lập kết nối qua 3 bước.
sequenceDiagram
participant C as Client
participant S as Server
C->>S: SYN (seq=100)
Note right of C: "Tôi muốn kết nối,\nsequence number của tôi là 100"
S-->>C: SYN-ACK (seq=300, ack=101)
Note left of S: "OK. Sequence của tôi là 300.\nTôi nhận được seq 100 của bạn."
C->>S: ACK (ack=301)
Note right of C: "Tôi nhận được seq 300 của bạn.\nKết nối sẵn sàng."
Mỗi bên chọn một sequence number ngẫu nhiên khi bắt đầu. Sequence number này là nền tảng để sắp xếp lại gói tin và phát hiện gói bị mất. Tại sao 3 bước chứ không phải 2? Vì cần xác nhận theo cả hai chiều — client cần biết server nghe được, và server cần biết client nhận được phản hồi.
Layer 3 — Truyền dữ liệu: sequence number và ACK
Mỗi byte dữ liệu được đánh số theo sequence number. Bên nhận xác nhận bằng ACK.
sequenceDiagram
participant C as Client
participant S as Server
C->>S: DATA (seq=101, bytes 1-1000)
C->>S: DATA (seq=1101, bytes 1001-2000)
S-->>C: ACK (ack=2101) — "nhận đủ đến byte 2100"
C->>S: DATA (seq=2101, bytes 2001-3000)
Note over C,S: ⚡ Gói tin bị mất trên đường
Note over S: timeout — không nhận được
S-->>C: ACK (ack=2101) — "vẫn đợi từ byte 2101"
C->>S: DATA (seq=2101) — gửi lại
Cơ chế này gọi là selective retransmission — chỉ gửi lại gói bị mất, không gửi lại từ đầu. TCP cũng có flow control (receiver window) và congestion control để không làm nghẽn mạng.
Layer 4 — 4-way FIN: đóng kết nối
Đóng kết nối cần 4 bước vì hai chiều độc lập — mỗi bên tự tuyên bố xong việc.
sequenceDiagram
participant C as Client
participant S as Server
C->>S: FIN
Note right of C: "Tôi xong rồi, không gửi nữa"
S-->>C: ACK
Note left of S: "OK, nhận được"
Note over S: Server có thể vẫn đang gửi dữ liệu
S-->>C: FIN
Note left of S: "Tôi cũng xong rồi"
C->>S: ACK
Note right of C: "OK. Chờ 2×MSL rồi đóng hẳn."
Note over C: TIME_WAIT (2 × MSL ≈ 60-120s)
TIME_WAIT là trạng thái client giữ sau khi gửi ACK cuối — để đảm bảo ACK đó đến được server. Nếu server không nhận ACK, nó sẽ gửi lại FIN và client cần còn "sống" để phản hồi. TIME_WAIT cũng ngăn sequence number cũ từ connection trước gây nhầm lẫn trong connection mới.
Full picture
sequenceDiagram
participant C as Client
participant S as Server
Note over C,S: 🤝 Mở kết nối
C->>S: SYN (seq=100)
S-->>C: SYN-ACK (seq=300, ack=101)
C->>S: ACK (ack=301)
Note over C,S: 📦 Truyền dữ liệu
C->>S: DATA (seq=101...)
S-->>C: ACK
S-->>C: DATA (seq=301...)
C->>S: ACK
Note over C,S: 👋 Đóng kết nối
C->>S: FIN
S-->>C: ACK
S-->>C: FIN
C->>S: ACK
Note over C: TIME_WAIT (60-120s)
Takeaway
TCP tồn tại vì Internet không đảm bảo điều gì. Handshake tốn 1 RTT trước khi dữ liệu đi — đó là chi phí cố định của mọi kết nối TCP mới. HTTP/2 giảm thiểu chi phí này bằng multiplexing. HTTP/3 đi xa hơn bằng cách bỏ hẳn TCP, dùng QUIC trên UDP để tự xử lý reliability.
Khi debug latency cao bất thường: kiểm tra số lần handshake. Keep-alive và connection pooling tồn tại đúng vì lý do này — mở kết nối mới không miễn phí.
Bài viết được hỗ trợ bởi Amy 🌸 - AI Assistant. Nội dung đã được kiểm duyệt bởi tác giả.
Related Posts
Zoom-in: Load Balancer
Một domain, hàng triệu request mỗi ngày. Load balancer không chỉ phân phối traffic — nó là điểm quyết định routing, health check, và session management cho toàn bộ hệ thống.
Zoom-in: DNS
Gõ 'google.com', nhấn Enter. Máy tính không hiểu tên miền — nó chỉ hiểu địa chỉ IP. Giữa hai thứ đó là một hệ thống phân tán với 4 tầng tra cứu.
Zoom-in: HTTP
Mọi ứng dụng web đều bắt đầu từ một mô hình đơn giản: client hỏi, server trả lời. HTTP là ngôn ngữ của cuộc hội thoại đó.