This article focuses on the core mechanisms of TCP and UDP at the transport layer. It explains how TCP achieves reliable delivery through the three-way handshake, four-way termination, sequence numbers, ACKs, retransmission, and window control, and also covers high-frequency topics such as SYN attacks, TIME_WAIT, and QUIC. Keywords: TCP handshake, four-way termination, reliable transport.
Technical specifications at a glance
| Parameter | Details |
|---|---|
| Domain | Computer Networking / Transport Layer |
| Core Protocols | TCP, UDP, QUIC, HTTP/3 |
| Content Format | Principles Analysis + State Machine + Interview Q&A |
| Original Source Platform | Curated from a CSDN blog post |
| Star Count | Not provided in the original article |
| Core Dependencies | TCP state machine, sliding window, timeout retransmission, Linux kernel queues |
This article systematically explains how TCP establishes and releases connections
TCP is a connection-oriented, reliable, byte-stream transport-layer protocol. Its value is not simply that it can send data, but that it can send data in order, with acknowledgments, and with recovery from failure. That is why backend services, database connections, and HTTP transport rely on TCP by default.
UDP is lighter weight. It is connectionless, has low header overhead, and supports multiple communication patterns, but it does not guarantee reliability, ordering, or deduplication. As a result, real-time audio and video, DNS, and game state synchronization often use UDP directly, while scenarios that need reliability add protocols such as QUIC on top.
TCP header fields define the foundation of reliability
AI Visual Insight: The image shows the typical layout of a TCP header, including source port, destination port, sequence number, acknowledgment number, header length, control flags, window size, checksum, and urgent pointer. This structure directly enables connection management, reliable acknowledgments, flow control, and abnormal reset handling, and it is the foundation for understanding handshakes, termination, and retransmission.
Sequence numbers solve out-of-order delivery and duplicate packet issues. The acknowledgment number indicates the next byte expected by the receiver. In essence, it tells the peer: I have received all data before this sequence number.
SYN initiates a connection, ACK confirms receipt, FIN closes a connection, and RST forcefully resets an abnormal connection. Without these control flags, TCP could not represent the lifecycle of a connection.
SYN = Initiate a connection
ACK = Acknowledge receipt
FIN = No more data will be sent
RST = Forcefully terminate an abnormal connection
This snippet summarizes the semantics of the four most important TCP control flags.
TCP must establish connections through a three-way handshake
AI Visual Insight: The image uses a timing diagram to show state transitions between the client and server from CLOSED and LISTEN to ESTABLISHED. The client sends SYN first, the server replies with SYN+ACK, and the client responds with ACK. The diagram emphasizes not just the exchange of three packets, but also synchronization of both initial sequence numbers and convergence of connection state.
First handshake: the client sends SYN along with its initial sequence number, client_isn. Second handshake: the server replies with SYN+ACK, acknowledges client_isn+1, and provides server_isn. Third handshake: the client acknowledges server_isn+1, and the connection is established.
The key point is that the third handshake can carry data, while the first two usually do not. The purpose of the first two is state synchronization, not application payload delivery.
The three-way handshake is not dogma but a balance between cost and reliability
AI Visual Insight: The image describes an abnormal scenario in which a stale SYN packet arrives at the server first. If the server entered the established state too early, it might allocate resources for an expired connection. The third handshake gives the client a chance to detect a mismatched acknowledgment number and send RST, preventing the stale connection from becoming valid.
The first value of the three-way handshake is that it prevents stale connection initialization. If an old SYN arrives first, the client will detect the acknowledgment mismatch and immediately reply with RST, allowing the server to release resources.
The second value is that it synchronizes both sides’ initial sequence numbers. A two-way handshake can only prove that one side can send and the other side can receive. It cannot prove that both initial sequence numbers have been acknowledged.
The third value is that it avoids resource waste. With only a two-way handshake, the server might allocate connection resources as soon as it receives SYN. Under network jitter, that behavior can create a large number of redundant connections.
AI Visual Insight: The image compares two-way, three-way, and four-way handshakes in terms of initial sequence number synchronization. It highlights that the three-way handshake is the minimal reliable solution: it completes bidirectional acknowledgment while avoiding the extra round-trip delay of a four-way handshake.
# Use pseudocode to describe the validation goal of the three-way handshake
client_send_syn() # Client sends its initial sequence number
server_send_syn_ack() # Server acknowledges the client's sequence number and sends its own initial sequence number
client_send_ack() # Client acknowledges the server's sequence number; only then is the connection truly established
This snippet shows that the core of the three-way handshake is bidirectional acknowledgment of the initial sequence numbers.
Packet loss, retransmission, and queue mechanics jointly determine handshake stability
If the ACK in the third handshake is lost, the client usually does not retransmit a pure ACK. Instead, the server retransmits SYN+ACK because it did not receive confirmation, and it keeps doing so until it reaches the timeout limit and gives up on the connection.
AI Visual Insight: The image shows the retransmission path after the third handshake is lost. The server remains in the SYN_RCVD state and repeatedly sends SYN+ACK, while the client sends ACK again after receiving it, until the states eventually converge to ESTABLISHED or the retry limit is reached.
After the server sends the second packet, it enters SYN_RCVD. At this point, the connection has not yet been delivered to the application layer. It first goes through the kernel’s connection management flow.
AI Visual Insight: The image shows the relationship among the listening socket, the half-open queue, the fully established queue, and accept(). It reveals that after the three-way handshake completes, the kernel maintains the connection first, and the application retrieves it through accept(), rather than the connection entering business logic immediately when the handshake finishes.
After the server receives SYN, it temporarily places the connection into the half-open queue. Once the third handshake completes, it moves the connection into the fully established queue. When the application calls accept(), it actually retrieves a connection object whose handshake has already completed.
A SYN flood is fundamentally an attack that exhausts the half-open queue
AI Visual Insight: The image shows the bidirectional retransmission process when the second handshake is lost: the client retransmits SYN and the server retransmits SYN+ACK. It demonstrates that packet-loss recovery during the handshake phase does not depend on only one side. Both sides retry according to the state machine.
A large number of SYN packets can fill the half-open queue, causing subsequent legitimate requests to be dropped and making clients experience connection timeouts. Common mitigation methods include increasing backlog, enlarging the SYN queue, enabling tcp_syncookies, and reducing the number of SYN+ACK retransmissions.
AI Visual Insight: The image illustrates the full path by which a connection moves from the half-open queue to the fully established queue. It emphasizes that only after the third-handshake ACK arrives does the kernel create a completed connection that accept() can consume.
AI Visual Insight: The image explains the SYN Cookies mechanism. When the SYN queue is full, the server no longer allocates half-open connection objects. Instead, it writes an encoded cookie into the sequence number field of the SYN+ACK packet, then validates and reconstructs the connection state only after the client returns ACK, thereby reducing resource consumption.
# Common Linux TCP hardening ideas
sysctl -w net.ipv4.tcp_syncookies=1 # Enable SYN Cookies
sysctl -w net.ipv4.tcp_synack_retries=3 # Reduce the number of SYN+ACK retransmissions
This snippet shows two typical kernel-parameter directions for mitigating SYN floods.
TCP releases connections through a four-way termination because it matches bidirectional shutdown semantics
AI Visual Insight: The image presents key states such as FIN_WAIT_1, CLOSE_WAIT, LAST_ACK, and TIME_WAIT in a state timing diagram. It shows that TCP connection teardown is not an instantaneous disconnect, but a process of bidirectional half-close, acknowledgment, and waiting for residual packets to disappear.
First termination: the active closer sends FIN and enters FIN_WAIT_1. Second termination: the passive side replies with ACK and enters CLOSE_WAIT. Third termination: after processing any remaining data, the passive side sends FIN and enters LAST_ACK. Fourth termination: the active side replies with ACK and enters TIME_WAIT.
In most cases, four-way termination cannot be compressed into three packets because ACK and FIN represent two different semantics: one confirms that you will send no more data, and the other states that I will also send no more data. Only when the server happens to have no more data to send and delayed acknowledgment applies can the second and third steps be merged.
TIME_WAIT is the final safeguard for reliable connection teardown
AI Visual Insight: The image explains a half-closed scenario in which the active closer stops sending but can still receive data. It highlights the semantic difference between shutdown and close, and it also explains why the connection does not necessarily become fully invalid immediately between the second and third termination steps.
TIME_WAIT waits for 2MSL for two purposes. First, it absorbs stale packets still in the network so that a new connection does not mistakenly receive leftover packets from an old connection. Second, if the final ACK is lost, the peer can retransmit FIN and still receive another acknowledgment.
AI Visual Insight: The image shows the retransmission and timeout path when a client FIN is lost. If the active closer eventually gives up retransmitting, the client may enter CLOSE while the server may still remain in ESTABLISHED, illustrating the real-world asymmetry of endpoint states during teardown.
If a server has a large number of TIME_WAIT connections, that usually does not mean the system is broken. The common cause is simply that the server is actively closing too many connections, for example because HTTP Keep-Alive is disabled, long-lived connections time out, or a per-connection request limit has been reached.
TCP reliability comes from a coordinated set of mechanisms rather than a single design point
Reliable TCP transport depends on six categories of mechanisms: connection management, sequence numbers, acknowledgment responses, timeout retransmission, flow control, and congestion control. Respectively, they answer these questions: can a connection be established, is data ordered, was anything lost, should data be retransmitted, can the receiver keep up, and is the network congested?
The biggest difference between UDP and TCP is not raw speed, but whether reliability is built in. The UDP header is only 8 bytes and preserves message boundaries clearly, but it does not guarantee ordering or delivery. TCP is a stream-based protocol with no native message boundaries, which is why sticky packet issues can occur.
# A common way to solve TCP sticky packets: define a custom message length field
def encode(msg: bytes) -> bytes:
length = len(msg).to_bytes(4, 'big') # Write the message length into the first 4 bytes
return length + msg # Length header + message body
This snippet demonstrates the basic idea of solving TCP sticky packets with a length-prefixed protocol.
Reliable HTTP-like transport can also be built on top of UDP
HTTP/3 does not run directly on TCP. It runs on QUIC. QUIC is built on UDP, but it adds capabilities such as connection migration, retransmission, congestion control, and forward error correction. As a result, it preserves the flexibility of UDP while gaining reliability close to TCP.
This is also the best real-world example of the statement: UDP is unreliable, but it can carry reliable protocols. Understanding this point is closer to engineering reality than mechanically repeating that TCP is reliable and UDP is unreliable.
FAQ
Why does the client usually not retransmit ACK if the third handshake is lost?
Because ACK itself is usually not controlled as a standalone retransmission unit. If the server does not receive the ACK, it retransmits SYN+ACK, and after the client receives it, the client sends ACK again. The state machine can converge on its own.
Why can a server accumulate a large number of TIME_WAIT connections?
Because only the side that actively closes the connection enters TIME_WAIT. If the server frequently closes HTTP connections actively, for example because Keep-Alive is disabled, an idle timeout is reached, or a request-count limit is triggered, TIME_WAIT can accumulate.
What is the root cause of TCP sticky packets?
Because TCP is a byte-stream protocol with no message boundaries. There is no one-to-one mapping between multiple write calls on the sender side and multiple read calls on the receiver side. In practice, developers usually solve this with fixed-length framing, delimiters, or a length field.
Core summary: This article systematically reconstructs the core transport-layer knowledge of TCP and UDP. It covers TCP header fields, the three-way handshake, four-way termination, TIME_WAIT, half-open queues, SYN attacks, reliable transmission, and a comparison of UDP and QUIC. It is well suited for interview review and backend troubleshooting.