Skip to main contentTCP | IoT Worker

TCP

When a page loads slowly, an API times out, or packet capture shows retransmissions and duplicate acknowledgements, the problem is often not HTTP itself. It is the transport connection beneath it. TCP is usually summarized as a “reliable transport protocol,” but the real engineering judgment comes from how it turns an unreliable network path into a usable byte stream through connection state, acknowledgement, retransmission, windows, and in-order delivery.

TCP’s cost is here too. It solved the reliable transport problem for the open Internet, but it also carried later Web performance constraints, weak-network behavior, and multiplexing limits down below the application layer. The reasons HTTP/2 gets stuck behind packet loss and QUIC wants to redesign transport again are both in TCP’s behavior model.

TCP does not mainly “guarantee data arrival.” It uses connection state, acknowledgements, retransmission, window control, and in-order delivery to build a sustainable byte stream on top of unreliable IP

Why It Appeared

IP solves “try your best to deliver packets to the destination address.” It does not solve “deliver a complete data sequence reliably for an application.” In the earlier network reality, that led to several problems:

  • Packets could be lost
  • Packets could arrive out of order
  • Packets could arrive more than once
  • The sender could be much faster than the receiver
  • The entire network could get congested under excessive sending

If every application had to solve those problems by itself, the cost would be high and interoperability would be poor. TCP’s value was to collect those common problems into one generic mechanism so applications could receive a continuous byte stream instead of a pile of disordered packets.

Who Built It and Under What Conditions

TCP came out of the early Internet protocol stack, driven by DARPA-supported work, and later became a key part of the TCP/IP family. It was not designed for a single vendor’s controlled data center. It was designed for heterogeneous hosts, long-distance links, and an unstable public Internet.

That set the design priorities:

  • The underlying network is assumed to be unreliable
  • The two endpoints are assumed to differ in speed and capability
  • A connection may last for a while rather than ending after one packet
  • Once deployed at scale, compatibility has to last a long time

So TCP is not a protocol optimized only for “fast file transfer inside a LAN.” It is a deliberately conservative, general-purpose transport layer for the open Internet.

Main Model

TCP is easiest to think of as four keywords:

  • Connection-oriented
  • Byte-stream oriented
  • Acknowledgement and retransmission
  • Flow control and congestion control

The byte-stream part is easy to underestimate. TCP does not know where one HTTP request, TLS record, or custom protocol message starts and ends. To TCP, the application hands over a sequence of bytes, and TCP tries to deliver that sequence to the other side reliably and in order.

That is both its strength and the source of many limits.

A Typical Path

sequenceDiagram participant C as Client participant S as Server C->>S: SYN S->>C: SYN + ACK C->>S: ACK C->>S: Data(seq=...) S->>C: ACK(ack=...) S->>C: Data(seq=...) C->>S: ACK(ack=...)

Behind that simple path, TCP is doing several things at once:

  • Confirming that both sides are willing to create a connection
  • Establishing sequence number space in both directions
  • Telling the other side which bytes have been received
  • Triggering retransmission when data is lost
  • Using windows and congestion control to avoid overwhelming either endpoint or the network

What looks like three-way handshake plus a stream of ACKs is really a continuously maintained connection-state machine.

Why Three-Way Handshake Exists

The point of the three-way handshake is to let both sides confirm two things:

  • The peer is reachable
  • The initial sequence numbers and connection state have been established

It can be shown like this:

sequenceDiagram participant C as Client participant S as Server C->>S: SYN(seq=x) S->>C: SYN(seq=y) + ACK(x+1) C->>S: ACK(y+1)

With only two steps, the server would not know whether the client received its SYN+ACK, and the connection state could remain half-open. The third step closes the loop and makes both sides know that the other side can send and receive.

That is why, when you see many SYN packets but not a complete three-way handshake, you usually start by checking reachability, firewalls, listening ports, or packet loss in the middle, not the application protocol first.

Why TCP Delivers In Order

TCP is not only reliable; it also promises in-order delivery. That simplifies application code:

  • Applications do not need to reorder out-of-order data themselves
  • Upper-layer protocols can parse a continuous byte stream
  • Many older protocol implementations can stay simple

The cost is large. If one earlier segment is missing, later data that has already arrived cannot be passed up yet. That is the root of TCP head-of-line blocking.

This design was natural for file transfer, database connections, and early Web traffic, where one connection usually carried one linear stream. Once HTTP/2 started multiplexing many requests over one connection, the problem became much more visible.

Why Acknowledgements and Retransmission Cost Performance

TCP trades reliability for acknowledgement and retransmission, but those are not free.

When a segment is lost, the sender usually detects it in one of two ways:

  • A timeout expires before acknowledgement arrives
  • Repeated duplicate acknowledgements suggest a missing segment in the middle

The missing data is then retransmitted. That keeps reliability intact, but it also creates follow-on costs:

  • Waiting for acknowledgements increases latency
  • Retransmission consumes bandwidth
  • In-order delivery delays data that already arrived later
  • Congestion control may reduce sending speed further

So the other side of “TCP is reliable” is that it spends more waiting, more state, and more conservative control to earn that reliability.

Why Window Control Is Necessary

TCP cannot let the sender run at full speed forever. There are at least two different limits.

The first is the receiver. It may not be able to absorb data fast enough, so the receive window tells the sender how much more it can take.

The second is the network itself. It may not tolerate a sustained high send rate, so congestion control limits how much data enters the path.

These two windows are often confused, but they solve different problems:

  • The receive window answers “can the other side keep up”
  • The congestion window answers “can the network keep up”

If throughput looks bad and you do not separate those two, it is easy to mistake a window issue for “not enough bandwidth.”

Why HTTP/2 Still Gets Stuck on TCP

HTTP/2 already multiplexes in the application layer, so multiple requests and responses can share one connection. But the transport beneath it is still TCP.

That means:

  • Multiple HTTP/2 streams share one TCP byte stream
  • If one TCP segment is lost, later segments, even for other streams, still have to wait
  • Application-layer multiplexing does not remove the transport-layer in-order blocking

That is why QUIC moved multiplexing semantics down into the transport layer. HTTP/2 has streams, but TCP only sees one byte stream.

What Four-Way Close Is Solving

Connection close is not just “disconnect.” TCP is full duplex, and both sides may still have data to send, so shutdown happens in two steps:

sequenceDiagram participant C as Client participant S as Server C->>S: FIN S->>C: ACK S->>C: FIN C->>S: ACK

One side sends FIN to say “I am done sending.” The other side acknowledges that, but it can still send its own remaining data before closing with its own FIN. That is why four packets are needed.

So when a connection enters FIN_WAIT or TIME_WAIT, it is still inside the close sequence, not fully released yet.

What to Look At in a Capture

TCP analysis is easiest if you do not start from the full header. A better order is:

First, Confirm the Connection Was Established

Check whether:

  • SYN
  • SYN+ACK
  • Final ACK

all completed. If the three-way handshake did not finish, check reachability, firewalls, listening ports, or middlebox loss before looking at the application.

Then Look for Retransmission, Duplicate ACKs, and Reordering

These signals carry a lot of meaning:

  • Retransmission
  • Dup ACK
  • Out-of-Order
  • Zero Window

They usually point to loss, receiver pressure, link instability, or path-quality issues.

Finally Check RTT and Window Changes

Many “sometimes fast, sometimes slow” problems are not caused by server logic alone. They are often caused by:

  • RTT growth
  • Congestion window shrinkage
  • Receive window shrinking
  • Retransmission disturbing the sending rhythm

If you only watch application latency and ignore this layer, the conclusion is often wrong.

How to Read TCP in Engineering Work

  • TCP is not just “reliable transport.” Its main cost is connection state, in-order delivery, and retransmission control
  • A byte stream is not a message stream, so the application must define message boundaries itself
  • Head-of-line blocking comes from TCP’s in-order delivery, not from HTTP/2 inventing extra trouble
  • Throughput problems are not only about bandwidth; windows, RTT, loss, and congestion control are often more important
  • QUIC is not a renamed TCP. It moves the transport-layer choices that modern Web needs into a new design

Further Reading

References