LUNAROPS · OPERATIONAL UPLINK 100% UPTIME 1,247d POSTS 893 JEFF.MOON@LUNAROPS.DEV UTC --:--:--

How TCP/IP Actually Won

tcp-iposi-modelnetworking-historyinternet-protocolsietfcomputing-historyprotocols

By the early 1980s, almost every serious person in networking believed the future belonged to OSI. Governments mandated it. Standards bodies poured a decade of committee work into it. Textbooks taught its seven layers as gospel, and they still do. Telecom incumbents — the people who actually owned the wires — backed it. TCP/IP, by contrast, was a research-network protocol family designed by a handful of academics and defense contractors, running on a network most of the planet had never heard of. And yet, by the mid-1990s, OSI was effectively dead on the wire and TCP/IP carried everything. This was not an accident, and it was not luck. TCP/IP won because of a specific set of architectural bets and cultural choices: a connectionless datagram model that pushed complexity to the edges, a development process that valued running code over paper standards, and — decisively — a free, working reference implementation that shipped on the exact machines researchers were already using. OSI lost not because its ideas were bad, but because it tried to design the network the way a phone company designs a switch: completely, correctly, and far too late.


Two Heritages: The Circuit and the Datagram

To understand the war you have to understand where each side came from, because the architectures encode the assumptions of their parents.

OSI grew out of the telecommunications world. Its intellectual ancestor was X.25, the packet-switching standard blessed by the CCITT (now the ITU-T), the international body of the national telephone monopolies — the PTTs. The PTT worldview was that the network is a smart, reliable, billable service provided by a carrier, and the endpoints are dumb terminals. A connection is a virtual circuit: you set it up, the network remembers it (state lives in the switches), data flows in order with the network guaranteeing delivery, and you tear it down. This is the mental model of a telephone call. It is connection-oriented to the bone. X.25 reliability, flow control, and sequencing all live inside the network.

TCP/IP grew out of ARPANET research, where the governing problem was different: how do you internetwork a collection of heterogeneous networks — packet radio, satellite links, leased lines, Ethernet — none of which you control and several of which are lossy and unreliable? Robert Kahn’s design constraint, formalized with Vint Cerf in their 1974 paper “A Protocol for Packet Network Intercommunication,” was that the internetwork layer should assume nothing about the reliability of the underlying networks. The network’s only job is to do its best to move a self-contained packet — a datagram — toward its destination. If a packet is dropped, duplicated, or reordered, that is fine; the endpoints will sort it out. State lives in the hosts, not the switches. This is connectionless. The network is dumb and the edges are smart — the exact inverse of the PTT model.

That single decision — connectionless IP underneath, with reliability bolted on top by TCP at the endpoints — is the philosophical core of the whole story. It later got a name: the end-to-end argument, articulated by Saltzer, Reed, and Clark in 1984. Functions like reliable, in-order delivery can only be completely and correctly implemented end to end at the application’s endpoints, so building them into the network is at best a performance optimization and at worst dead weight. OSI and X.25 put reliability in the network. TCP/IP refused to.


The 1974 Design and the Great Split

Cerf and Kahn’s original 1974 protocol was a single monolithic thing called TCP — the Transmission Control Program — that handled both addressing/routing and reliable delivery. As the design matured through the late 1970s, the architects made a move that turned out to be one of the most consequential refactorings in computing history: they split it.

The routing-and-addressing part became the Internet Protocol (IP), a pure connectionless datagram service that does nothing but best-effort delivery of a packet from a source address to a destination address. The reliability part — sequencing, retransmission, flow control, the handshake — became the Transmission Control Protocol (TCP), layered on top. And crucially, they left a hole next to TCP: if you did not want reliability and just wanted to fire datagrams with minimal overhead, you could use the User Datagram Protocol (UDP) instead, a paper-thin wrapper over IP. This split was ratified in the foundational RFCs of 1981: RFC 791 (IP), RFC 793 (TCP), with UDP already specified in RFC 768 (1980).

The genius of the split is that it cleanly separated what the network guarantees (almost nothing) from what the endpoints want (varies by application). A file transfer wants reliability and uses TCP. Real-time voice would rather drop a packet than wait for a retransmission, so it uses UDP. OSI, by contrast, spent years agonizing over whether its network layer should be connectionless or connection-oriented and ultimately — in classic committee fashion — standardized both (CLNP, the Connectionless Network Protocol, and the connection-oriented mode), which meant implementers had to support two incompatible philosophies and nobody could assume which they would meet.


The Two Stacks, Side by Side

Here is the mapping everyone half-remembers. The seven OSI layers do not cleanly correspond to the four TCP/IP layers, and pretending they do causes endless confusion.

OSI layer OSI name TCP/IP layer TCP/IP examples
7 Application Application HTTP, SMTP, DNS, SSH, BGP
6 Presentation (folded into application) TLS, character encoding, MIME
5 Session (folded into application) TLS session resumption, RPC
4 Transport Transport TCP, UDP
3 Network Internet IP, ICMP, routing
2 Data Link Link Ethernet, Wi-Fi, PPP
1 Physical Link copper, fiber, radio

The TCP/IP model collapses OSI’s top three layers into one “application” layer and its bottom two into one “link” layer. This is not sloppiness; it reflects a real observation. OSI’s Presentation and Session layers turned out to be solutions in search of a problem for most applications — and when they were needed (encryption, session resumption), the functions migrated into the application protocol or into TLS rather than living in a mandatory, separate layer. Meanwhile the physical/data-link distinction, while real, is almost always handled by the same hardware and driver, so TCP/IP treats it as one concern.

        OSI MODEL                    TCP/IP MODEL
   +------------------+          +------------------+
 7 |   Application    |  \       |                  |
   +------------------+   \      |                  |
 6 |  Presentation    |    >---->|   Application    |
   +------------------+   /      |                  |
 5 |     Session      |  /       |                  |
   +------------------+          +------------------+
 4 |    Transport     | -------> |    Transport     |
   +------------------+          +------------------+
 3 |     Network      | -------> |     Internet     |
   +------------------+          +------------------+
 2 |    Data Link     |  \       |                  |
   +------------------+   >----->|       Link       |
 1 |    Physical      |  /       |                  |
   +------------------+          +------------------+

If you want the practical, troubleshooting-oriented version of this mapping — where each protocol actually lives and how to use the layers to isolate a fault — see the OSI and TCP/IP models in practice.


What Encapsulation Actually Looks Like

The abstraction is concrete on the wire. When a process sends data over TCP, each layer wraps the layer above it. Consider an HTTP request going out over Ethernet:

  +-----------------------------------------------------------+
  | Ethernet | IP   | TCP  |        HTTP payload       | FCS  |
  | header   | hdr  | hdr  |  "GET / HTTP/1.1\r\n..."  |      |
  +-----------------------------------------------------------+
  |<--14B--->|<-20B>|<-20B>|<-------- data ---------->|<-4B-->|

  Link layer  -> frames the IP packet, adds MAC addrs + FCS
  Internet    -> IP header: src/dst IP, TTL, protocol=6 (TCP)
  Transport   -> TCP header: src/dst port, seq, ack, flags
  Application -> the bytes the program actually wrote

Each layer only reads its own header. A switch rewrites the Ethernet frame and never looks deeper. A router reads the IP header, decrements the TTL, makes a forwarding decision, and re-frames for the next hop — it does not care that there is a TCP segment inside, let alone an HTTP request. That strict layering is what lets the same IP packet ride over Ethernet, then a fiber backbone, then Wi-Fi, without any layer needing to understand the others. The same principle underlies how packets cross the physical layer of undersea cables without the transport layer ever knowing.

You can watch the IP-level protocol number and headers directly:

1
2
3
4
5
6
7
8
$ ip route get 1.1.1.1
1.1.1.1 dev eth0 src 192.168.1.50 uid 1000
    cache

$ ss -tn state established
Recv-Q  Send-Q   Local Address:Port    Peer Address:Port
0       0        192.168.1.50:51324    140.82.113.25:443
0       0        192.168.1.50:48820    1.1.1.1:443

The protocol=6 field in the IP header is the demultiplexing key that says “the payload is TCP.” UDP is 17, ICMP is 1. That one byte is how IP stays gloriously ignorant of what it carries.


Rough Consensus and Running Code

If the architecture explains what TCP/IP was, the development culture explains why it shipped while OSI did not.

OSI was built the way standards have always been built in telecom: a formal hierarchy of ISO and CCITT working groups, national-body representatives, voting, and exhaustive paper specifications produced before anybody was required to build the thing. The goal was completeness and political consensus among governments and vendors. The result was a set of standards that were rigorous, comprehensive, and frequently ambiguous or self-contradictory in the ways that only design-by-committee produces — and that arrived years after the problems they addressed had already been solved in the field.

The IETF worked the opposite way, and codified its ethos in a phrase from Dave Clark in 1992: “We reject kings, presidents and voting. We believe in rough consensus and running code.” Specifications were RFCs — Requests for Comments, a name that itself signals the culture — and the bar for a standard advancing was that multiple independent, interoperating implementations actually existed. You did not standardize a feature and then hope someone built it; you built it, made it interoperate, and then wrote it down. The feedback loop ran through working software, not committee minutes. The whole machinery, from the early ARPANET handoffs through to modern interdomain routing, is part of the long arc of how the Internet learned to trust itself.

The difference compounds. Running code surfaces the ambiguities a paper spec hides. By the time OSI committees were still arguing about the semantics of a service primitive, the TCP/IP community had three implementations talking to each other and had moved on. “Running code” is not a slogan; it is a debugging strategy applied to the standards process itself.


The Reference Implementation That Decided It

Here is the single most underrated reason TCP/IP won, and it is almost embarrassingly mundane: it came free, in source, on the computers researchers already had.

In the early 1980s, DARPA funded the integration of TCP/IP into Berkeley’s BSD Unix. The 4.2BSD release in 1983 shipped a complete, working TCP/IP stack and a new programming interface for it — the sockets API — and BSD ran on the VAX and other machines that populated university computer-science departments, the exact population building the next generation of networked software. You did not buy an OSI stack from a vendor, wait for delivery, and pay per seat. You got TCP/IP for the cost of a tape, with source you could read and fix. (For the deeper story of how Unix itself spread through academia and made this possible, see the story of Unix.)

The sockets API mattered as much as the stack. It made network I/O look like file I/O — a paradigm Unix programmers already understood — and gave a single, concrete, portable way to write network programs. A minimal TCP client is just this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(void) {
    int s = socket(AF_INET, SOCK_STREAM, 0);   /* TCP socket */

    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(80);
    inet_pton(AF_INET, "93.184.216.34", &addr.sin_addr);

    connect(s, (struct sockaddr *)&addr, sizeof(addr));

    const char *req = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
    write(s, req, strlen(req));

    char buf[4096];
    ssize_t n;
    while ((n = read(s, buf, sizeof(buf))) > 0)
        write(STDOUT_FILENO, buf, n);   /* socket reads like a file */

    close(s);
    return 0;
}

SOCK_STREAM gives you TCP; SOCK_DGRAM gives you UDP. That is the whole transport choice, exposed as one argument. OSI had a comparably ambitious service interface on paper, but there was no equivalent universal, free, debugged implementation that every student could connect() against on a Tuesday afternoon. The sockets API became the de facto standard for network programming on every platform that mattered — and still is, four decades later. When the tool that everyone learns on speaks one protocol family natively, that family wins by default. This same BSD lineage is why Linux networking fundamentals still revolve around the sockets model and IP-centric tooling today.


The Government Tried to Mandate OSI — and Failed

The proponents of OSI were not naive about TCP/IP’s momentum, so they did the thing institutions do when the market is drifting away from them: they tried to legislate.

In the United States, this took the form of GOSIP — the Government OSI Profile — issued as FIPS 146 in 1990, which mandated that federal agencies procure OSI-compliant networking products. The United Kingdom and other governments had parallel mandates. The bet was that the buying power of the world’s governments would force vendors to ship OSI and force the market to follow.

It did not work, and the reasons are instructive. Mandating procurement of OSI-capable products is not the same as mandating use. Agencies dutifully bought boxes that could speak OSI and then ran TCP/IP on them, because TCP/IP was what actually interoperated, what their staff knew, and what the applications they wanted were written for. The OSI products were expensive, late, incompletely implemented, and frequently failed to interoperate across vendors — the precise failure mode that “running code with multiple interoperating implementations” was designed to prevent. By the time fully usable OSI stacks existed, the Internet had already won the network effect: every new host that joined spoke TCP/IP, which made TCP/IP more valuable, which made the next host choose it too. GOSIP was quietly gutted in the mid-1990s as the government acknowledged reality and began permitting — then assuming — TCP/IP. A mandate cannot beat a network effect plus a free reference implementation.


What OSI Got Right, and What Survived

It would be a cheap and false story to say OSI was simply wrong. It was, in several respects, more rigorous than TCP/IP, and important pieces of it are load-bearing infrastructure today — you are almost certainly using some right now.

  • The seven-layer model as pedagogy. As a protocol architecture the seven layers lost, but as a teaching and troubleshooting vocabulary the model is universal. “It’s a Layer 2 problem” versus “it’s a Layer 7 problem” is OSI’s language, and it remains the lingua franca of network engineering precisely because it cleanly separates concerns even when the implementation does not honor the boundaries.
  • ASN.1. Abstract Syntax Notation One, OSI’s data-description and serialization framework, is everywhere: it is the encoding behind X.509 certificates, SNMP, LDAP, and large parts of the cellular telephone network’s signaling. Every time your browser validates a TLS certificate, it parses ASN.1 (DER-encoded).
  • X.509. The certificate format that underpins TLS and therefore HTTPS is an OSI-world artifact (from the X.500 directory work). The trust model evolved, but the certificate structure is OSI’s.
  • X.500 to LDAP. OSI’s X.500 directory was too heavy to deploy as designed, but its data model and naming survived: LDAP — the Lightweight Directory Access Protocol — is literally X.500’s directory access protocol, stripped down to run over TCP/IP. Active Directory and most enterprise identity systems are X.500’s descendants.

The pattern is consistent. The application-layer ideas of OSI — naming, directories, certificates, structured data description — were genuinely good and survived, usually after being lifted out of the OSI stack and re-hosted on top of TCP/IP. What died was OSI’s lower-layer ambition: the idea of a smart, connection-oriented, committee-specified network and transport substrate. The market kept the good APIs and threw away the heavy plumbing. The result is the layered design you see in modern routing, where IP’s dumb-network bet enabled scalable interdomain systems like BGP and the global naming layer of DNS to be built on top by independent communities, exactly as the end-to-end argument predicted.


The Timeline of a Slow Victory

The win was not a single moment, but the ARPANET flag day comes closest to one. On 1 January 1983, the ARPANET cut over from the older NCP (Network Control Program) to TCP/IP in a coordinated “flag day” — every host had to switch on the same date, and stragglers wore buttons reading “I survived the TCP/IP transition.” That cutover made TCP/IP the native language of the research network at the exact moment that network was about to explode into the Internet.

 1974  Cerf & Kahn publish the TCP design
 1980  UDP specified (RFC 768)
 1981  IP, TCP, ICMP ratified (RFC 791/793/792)
 1983  ARPANET flag-day cutover to TCP/IP; 4.2BSD ships sockets
 1984  OSI 7-layer reference model published (ISO 7498)
       end-to-end argument paper (Saltzer/Reed/Clark)
 1990  GOSIP mandate (FIPS 146)
 1991  Dave Clark: "rough consensus and running code"
 1995  NSFNET decommissioned; commercial Internet on TCP/IP
       GOSIP effectively dead; OSI gone from the wire

By the time ISO published the canonical seven-layer reference model in 1984, the protocol family that would actually carry the world’s traffic had already been running in production for a year and shipping free with source for the same length of time. OSI’s reference model arrived as a beautifully organized description of a network that the future had already decided not to build.


Verdict

TCP/IP did not win because it was more elegant — in several respects OSI was the more carefully reasoned architecture. It won because of a coherent stack of pragmatic bets that each reinforced the others. The connectionless datagram model made the network simple enough to actually build and to span wildly heterogeneous links, while the end-to-end argument put the complex, application-specific reliability logic where it belonged: at the edges. The “rough consensus and running code” culture meant standards were debugged by real interoperation before they were blessed, instead of after. And the free BSD reference implementation with the sockets API put working TCP/IP on the exact machines that the people building the future were already using, so the protocol spread by default rather than by decree. OSI tried to win by completeness and mandate and lost to working code plus a network effect — a lesson the industry has relearned many times since.

The honest epilogue is that OSI’s best ideas did not die; they emigrated. ASN.1, X.509, and LDAP are OSI refugees thriving on top of the TCP/IP stack, and the seven-layer model remains the language every network engineer reasons in. The deepest lesson is not “simple beats complex” — it is that the architecture which gets deployed, iterated, and handed to builders for free writes the rules everyone else has to live with. TCP/IP shipped. That, more than any layer diagram, is how it actually won.


Sources

Comments