This article focuses on network layering, TCP reliable transport, and the evolution of HTTP/3 and QUIC. It explains the three-way handshake, four-way teardown, congestion control, and packet capture fundamentals to help developers understand timeouts, head-of-line blocking, and weak-network optimization. Keywords: TCP, UDP, HTTP/3.
Technical Specification Snapshot
| Parameter | Content |
|---|---|
| Domain | Computer Networking / Transport Layer / Application Layer |
| Core Protocols | TCP, UDP, HTTP/1.1, HTTP/2, HTTP/3, QUIC |
| Article Type | Protocol internals and practical troubleshooting |
| Language | Chinese |
| Key Mechanisms | Three-way handshake, four-way teardown, congestion control, multiplexing, 0-RTT |
| Common Tools | Wireshark, Charles, Fiddler |
| Stars | Not provided in the original |
| Core Dependencies | TCP/IP stack, TLS 1.3, UDP |
Network communication is fundamentally a layered and decoupled collaboration system
Internet communication does not rely on a single protocol. It works through layered collaboration. The application layer defines data semantics, the transport layer determines how processes deliver data to each other, the network layer handles addressing and routing, the link layer forwards frames within a local network, and the physical layer carries the raw bit stream.
What developers most often confuse is the difference between data content and transport method. HTTP cares about request semantics, TCP and UDP care about how data is delivered, and IP only cares about where it should go. The value of layering is that it isolates complexity, so upper-layer business logic does not need to understand differences in the underlying medium.
A request is encapsulated layer by layer
When a browser sends a request, the original data is wrapped with headers at each layer: the HTTP header, TCP header, IP header, and Ethernet frame header. The receiver decapsulates the packet in the reverse order. This process explains why packet captures can show ports, sequence numbers, IP addresses, and MAC addresses at the same time.
Application Data -> TCP Segment -> IP Datagram -> Ethernet Frame -> Bit Stream
This flow shows the standard data encapsulation path in the protocol stack.
TCP achieves reliable transport through a state machine and acknowledgment mechanisms
The core value of TCP is not speed. It is reliability, ordering, and recoverability. Through sequence numbers, acknowledgments, retransmissions, sliding windows, and congestion control, TCP makes unstable networks behave like a stable byte stream. That is why database connections, file transfer, and most web services have relied on TCP for so long.
The goal of the three-way handshake is not greeting, but capability synchronization
In the first handshake, the client sends a SYN and declares its initial sequence number. In the second handshake, the server replies with SYN+ACK, which both confirms receipt and synchronizes its own sequence number. In the third handshake, the client sends ACK again to confirm that the server has normal send and receive capability.
If only two handshakes were used, a delayed historical SYN could be mistaken by the server as a new connection. The server might then allocate resources and wait for data that will never arrive, creating an invalid connection. The three-way handshake fundamentally exists to eliminate interference from stale packets and verify bidirectional communication capability.
states = ["SYN_SENT", "SYN_RCVD", "ESTABLISHED"]
seq_client = 100 # Initial client sequence number
seq_server = 300 # Initial server sequence number
# First handshake: the client sends SYN
send = f"SYN seq={seq_client}" # The client declares send capability
# Second handshake: the server returns SYN+ACK
reply = f"SYN seq={seq_server}, ACK={seq_client + 1}" # The server confirms receipt and synchronizes its own sequence number
# Third handshake: the client sends ACK
final_ack = f"ACK={seq_server + 1}" # The client confirms the server's send capability
This code expresses the sequence number synchronization process of the three-way handshake with a minimal model.
The four-way teardown reflects how a TCP full-duplex connection actually closes
Closing a connection usually takes four steps because the sending channels in each direction are independent. When the client sends FIN, it only means “I will not send more data.” It does not mean the server has no data left to send. The server first replies with ACK, and after sending any remaining data, it sends its own FIN.
TIME_WAIT is the most critical and most misunderstood state in the shutdown process. On one hand, it allows the final ACK to be retransmitted if it is lost. On the other hand, it ensures that residual packets from the old connection fully expire, preventing them from contaminating a later connection with the same four-tuple.
Congestion control determines whether TCP can converge safely in complex networks
TCP does more than guarantee reliability for a single connection. It also avoids overwhelming the entire network. Slow start probes available capacity through exponential growth. After reaching the threshold, TCP enters congestion avoidance and switches to linear growth. When duplicate ACKs or timeouts occur, TCP triggers fast retransmit and fast recovery to reduce the window proactively.
Slow Start: cwnd grows exponentially
Congestion Avoidance: cwnd grows linearly
Packet Loss Detected: ssthresh = cwnd / 2
Fast Recovery: avoids falling back directly to minimum throughput
These rules summarize TCP’s basic adjustment strategy under congestion.
The main thread of HTTP evolution has always been reducing latency and blocking
The history of HTTP upgrades is essentially a continuous effort to reduce connection setup cost, header overhead, and the scope of blocking. Protocol version changes are not just syntax upgrades. They are reconstructions of the transport model: from short-lived connections to persistent connections, from serialized responses to multiplexing, and finally to bypassing the transport constraints imposed by TCP.
HTTP/1.1 reduced repeated connection setup, but did not eliminate blocking
In HTTP/1.0, each requested resource required a new TCP connection. As page resources increased, handshake overhead grew rapidly. HTTP/1.1 introduced Keep-Alive, which allowed connection reuse and improved throughput, but request and response ordering still remained tightly coupled, so application-layer head-of-line blocking persisted.
HTTP/2 improved multiplexing, but it was still constrained by TCP packet loss
HTTP/2 splits messages into frames and allows multiple streams to be interleaved over the same connection, enabling multiplexing. Combined with HPACK header compression, it significantly reduces repeated header overhead. This is especially important for high-concurrency page loading.
However, HTTP/2 still runs on top of TCP. Once a TCP packet is lost at the transport layer, the entire connection must wait until retransmission completes. In other words, HTTP/2 solved application-layer head-of-line blocking, but it did not eliminate transport-layer head-of-line blocking.
HTTP/3 redefines the boundary of reliable transport through QUIC
HTTP/3 is built on QUIC, and QUIC is built on UDP. This is not simply “sending HTTP over UDP.” Instead, QUIC reimplements reliable transport, flow control, multiplexing, and encrypted handshakes in user space, while merging TLS negotiation with transport connection setup to significantly reduce time to first byte.
QUIC provides three major advantages. First, it supports 0-RTT or 1-RTT connection establishment. Second, packet loss in one stream does not block other streams. Third, it uses a Connection ID to identify a connection, making it easier to preserve session continuity during mobile network switches.
protocols = {
"HTTP/1.1": "TCP + Keep-Alive", # Reuses connections, but serialized blocking may still occur
"HTTP/2": "TCP + Multiplexing", # Solves application-layer blocking
"HTTP/3": "QUIC(UDP) + Multi-Stream", # Solves transport-layer head-of-line blocking
}
for name, feature in protocols.items():
print(f"{name}: {feature}") # Output the core transport characteristics of each HTTP version
This code provides a quick comparison of the transport capabilities behind each generation of HTTP.
Packet capture and connection keepalive are foundational skills for troubleshooting production systems
Keep-Alive has two completely different meanings. HTTP Keep-Alive belongs to the application layer, and its goal is connection reuse to reduce handshake overhead. TCP Keep-Alive belongs to the kernel transport layer, and its goal is to detect whether the peer is still alive so the system can clean up zombie connections in time.
| Dimension | HTTP Keep-Alive | TCP Keep-Alive |
|---|---|---|
| Layer | Application Layer | Transport Layer |
| Goal | Improve throughput | Detect connection liveness |
| Typical Scenarios | Page loading, API calls | Long-lived connections, databases, sockets |
| Configuration | Connection: keep-alive |
SO_KEEPALIVE |
The operating position of a packet capture tool determines what it can see
Wireshark primarily works near the link layer or network layer. It relies on NIC promiscuous mode to capture passing frames and is well suited for analyzing TCP retransmissions, window changes, DNS, and TLS behavior. Charles and Fiddler are essentially proxy tools that mainly intercept HTTP and HTTPS application traffic.
When proxying HTTPS, you must install a root certificate. The principle is that the client trusts a temporary certificate issued by the proxy, allowing decryption and re-encryption to occur locally. This is not breaking TLS. It is a legitimate man-in-the-middle debugging technique in a controlled environment.
 AI Visual Insight: This image appears closer to an ad slot or site visual placeholder. It does not contain technical information such as protocol structure, topology relationships, or packet flow direction, so it does not qualify as extractable protocol-level visual evidence.
From entering a URL to rendering a page, the process is a complete protocol pipeline
A typical page visit triggers DNS lookup, transport-layer connection establishment, TLS handshake, HTTP request transmission, server-side processing, and browser rendering. If the connection uses HTTP/3, the path for connection establishment and encryption negotiation is shorter. If it uses HTTP/2, focus on the gains from multiplexing. If it uses HTTP/1.1, focus on connection reuse and blocking behavior.
For developers, the greatest value of understanding this path is not memorizing definitions. It is being able to map timeouts, slow page loads, weak-network failures, certificate errors, and connection jitter to specific layers, then use packet capture, logs, and metrics to pinpoint the root cause.
FAQ
Q1: Why does HTTP/3 choose UDP and still guarantee reliability?
A1: Because reliability is no longer provided by kernel-space TCP. Instead, QUIC implements it on top of UDP, including sequence management, acknowledgments and retransmissions, flow control, and congestion control. This preserves control while removing much of TCP’s historical baggage.
Q2: Is the third ACK in the three-way handshake really necessary?
A2: Yes. It confirms that the client has received the server’s SYN, which prevents the server from mistakenly establishing a connection due to stale packets and holding resources for too long. Without the third confirmation, half-open connection problems would become more serious.
Q3: Why does HTTP/3 often perform better in mobile network scenarios?
A3: Because packet loss is more frequent on unstable networks. HTTP/2 over TCP can have the entire connection delayed by a single packet loss, while QUIC isolates the impact at the stream level and supports connection migration, which usually makes it more stable during transitions between Wi-Fi and cellular networks.
Core Summary: This article systematically reconstructs TCP/IP layering, the TCP three-way handshake and four-way teardown, congestion control, and the key differences among HTTP/1.1, HTTP/2, and HTTP/3, helping developers build a complete networking model from packet capture troubleshooting to performance optimization.