
TCP/IP 4 Layers: Reality Check
OSI 7 Layer is Theory. TCP/IP 4 Layer is Reality. Pragmatism beats Perfectionism.

OSI 7 Layer is Theory. TCP/IP 4 Layer is Reality. Pragmatism beats Perfectionism.
Why does my server crash? OS's desperate struggle to manage limited memory. War against Fragmentation.

Two ways to escape a maze. Spread out wide (BFS) or dig deep (DFS)? Who finds the shortest path?

Fast by name. Partitioning around a Pivot. Why is it the standard library choice despite O(N²) worst case?

Establishing TCP connection is expensive. Reuse it for multiple requests.

While building backend servers, I kept running into certain terms: "TCP connection," "IP address," "HTTP request," "port number." I couldn't connect the dots. The OSI 7-layer model I briefly saw in school felt overly complex, and nobody in the industry seemed to talk about it. Then someone told me, "You only need to know TCP/IP 4 layers in practice," and it felt like a wake-up call.
That was it. What I needed wasn't exam theory but the actual mechanics of how the Internet works right now. So I decided to dig deep into the TCP/IP model.
The first confusion: "Why are there two models?" Every networking book mentions OSI 7 layers, but all real-world documentation uses TCP/IP 4 layers. "Why not just pick one?" I thought.
The second confusion was about layer relationships. I understood that "data created at the Application Layer goes down to the Transport Layer," but I couldn't visualize how it gets "wrapped" and "passed along." The word "encapsulation" threw me off since I only knew it from object-oriented programming.
The third issue was connecting it to actual code. Calling fetch() seems like one step, but when does it traverse all four layers? Where in my code does the layer switch happen? It wasn't clear.
The turning point came when I compared it to the postal system.
When you mail a letter, what you do (write the letter), what the post office does (sort and ship), and what the delivery driver does (final delivery) are completely separate. I don't need to know the post office's internal sorting system, and I don't need to understand the delivery truck's engine. Each step handles its job and passes the "wrapped package" to the next stage.
TCP/IP works the same way.
Each layer only talks to the layer directly above or below it, never skipping. This is the essence of layering. Thanks to this, application developers don't need to know TCP internals, and router manufacturers don't need to know what HTTP is.
The OSI 7-layer model was designed in the late 1970s by ISO (International Organization for Standardization) to create a "perfect networking standard." It had cleanly separated layers like Session, Presentation, and Application. The problem? It was too complex, and while committees debated standards, actual implementation lagged.
In contrast, TCP/IP was developed in the late 1960s by DARPA (US Department of Defense) with a "just make it work" pragmatism. Instead of perfect separation, they valued "something that actually functions." So they merged OSI layers 5 (Session), 6 (Presentation), and 7 (Application) into one. Most applications handle session management and data representation internally anyway, so there's no need for separate layers.
As a result, TCP/IP got deployed on the real Internet first, while OSI remained a "theoretical reference model." OSI 7 layers are still taught because they're a good conceptual framework for understanding networking. But in actual implementation, TCP/IP 4 layers are the standard.
The bottom layer. Handles physical bit transmission.
Protocols like Ethernet, Wi-Fi, and PPP operate here. This layer sends electrical signals through cables, radio waves through air, or light through fiber optics. MAC addresses (physical addresses) are used here.
Think of it as the "roads" that carry letters. Whether the road is dirt or highway (Ethernet vs. Wi-Fi) affects speed, but upper layers don't care. They just trust that "if I send it down, it'll get physically delivered."
Developers rarely touch this layer directly. The operating system and network drivers handle it. However, when using packet capture tools (tcpdump, Wireshark), you can see Ethernet frames from this layer.
The layer that "crosses networks." This is where IP (Internet Protocol) operates.
IP's core role is routing. It determines the path from source IP address (e.g., 192.168.0.5) to destination IP address (e.g., 8.8.8.8). The Internet is a massive network of millions of routers, and each router decides the "next hop" and relays packets forward.
Think of it as writing "123 Main St, New York" on a package. Intermediate distribution centers (routers) look at this address and decide, "This is headed to New York, so put it on that truck."
A key concept here is NAT (Network Address Translation). Multiple devices at home (laptop, phone, TV) all use private IPs (192.168.x.x), but when going out to the Internet, they get "translated" into one public IP. When port numbers are also changed, it's called NAPT (Network Address Port Translation) or PAT (Port Address Translation).
For example, if my laptop (192.168.0.10:5000) and phone (192.168.0.20:6000) both connect to Google, the router changes them to public IP (e.g., 203.x.x.x:10001, 203.x.x.x:10002). When responses come back, it translates them back to the original private IPs. This is why "you can use multiple devices with one router at home."
Decides "how" to deliver data. TCP and UDP are the two main protocols.
TCP (Transmission Control Protocol) focuses on "reliability." It establishes connections with a 3-way handshake, guarantees packet order, and retransmits lost packets. Used for web browsing (HTTP/HTTPS), email (SMTP), and file transfer (FTP). Perfect for "this letter must arrive!" scenarios.
UDP (User Datagram Protocol) focuses on "speed." No connection setup, no delivery confirmation. Just send and forget. But it's fast. Used for real-time streaming (YouTube, Netflix), online gaming, and DNS queries. Ideal for "a few lost packets are fine, the next frame is coming anyway."
This is where port numbers come in. IP addresses specify "which computer," and port numbers specify "which program on that computer." For example:
142.250.207.46:443 = Google server's HTTPS program192.168.0.10:3000 = My laptop's development serverPort numbers allow multiple network programs to run simultaneously on one computer.
Where the programs users actually interact with operate.
HTTP/HTTPS (web), SMTP (email send), IMAP/POP3 (email receive), FTP (file transfer), SSH (remote access), DNS (domain lookup) all belong here.
When a developer calls fetch('https://api.example.com/users'), it starts at the Application Layer. It creates an HTTP request message and sends it down to lower layers.
In the OSI model, Session Layer (connection management) and Presentation Layer (encryption, compression, encoding) were separated, but TCP/IP merged all of this into the Application Layer. HTTPS handles TLS encryption internally, HTTP/2 handles compression internally. No need for separate layers. Pure pragmatism.
The core of the TCP/IP model is encapsulation. Each layer treats data from the upper layer as "cargo" and adds its own header.
[Application Data]
↓ (Transport Layer adds TCP header)
[TCP Header | Application Data] ← TCP Segment
↓ (Internet Layer adds IP header)
[IP Header | TCP Header | Application Data] ← IP Packet
↓ (Network Interface Layer adds Ethernet header/trailer)
[Eth Header | IP Header | TCP Header | Application Data | Eth Trailer] ← Ethernet Frame
Think of it as putting a letter in an envelope (Transport), putting that envelope in a box (Internet), and loading that box onto a delivery truck (Network Interface). Each step adds another layer of "packaging."
On the receiving end, decapsulation happens in reverse. Strip off the Ethernet header, strip off the IP header, strip off the TCP header, and finally extract the original data.
What happens when you type curl https://example.com in the terminal?
curl creates an HTTP request message.
GET / HTTP/1.1
Host: example.com
User-Agent: curl/7.88.1
Accept: */*
This is the Application Layer data. Now it gets sent down.
Step 2: Transport LayerThe OS's TCP stack receives it and adds a TCP header.
[SRC PORT: 54321 | DST PORT: 443 | SEQ: 1000 | ACK: 0 | FLAGS: SYN | ... | HTTP Request]
This is a TCP Segment.
Step 3: Internet LayerThe OS's IP stack adds an IP header.
[SRC IP: 192.168.0.10 | DST IP: 93.184.216.34 | TTL: 64 | PROTOCOL: TCP | ... | TCP Segment]
This is an IP Packet.
Step 4: Network Interface LayerThe network driver adds Ethernet header and trailer.
[SRC MAC: AA:BB:CC:DD:EE:FF | DST MAC: 11:22:33:44:55:66 | TYPE: IPv4 | IP Packet | CRC]
This is an Ethernet Frame, the final form transmitted over cables or Wi-Fi.
What Happens NextThe frame goes through the router (NAT router), where the Source IP gets changed to a public IP. It then hops through multiple intermediate routers hop-by-hop until reaching example.com's server. The server decapsulates it and finally extracts the HTTP request.
Usually, we use high-level libraries like fetch() or axios, but you can also directly control TCP sockets at a lower layer.
const net = require('net');
// Create TCP client (directly controlling Transport Layer)
const client = net.createConnection({ port: 80, host: 'example.com' }, () => {
console.log('TCP connection established!');
// Manually write HTTP request message (Application Layer)
client.write('GET / HTTP/1.1\r\n');
client.write('Host: example.com\r\n');
client.write('Connection: close\r\n');
client.write('\r\n');
});
// Receive response
client.on('data', (data) => {
console.log('Received data:', data.toString());
});
client.on('end', () => {
console.log('Connection closed');
});
This code uses net.createConnection() to directly create a Transport Layer TCP connection. Then client.write() sends an Application Layer HTTP message manually.
Normally, HTTP libraries hide this process, but here the layer separation is crystal clear. TCP only provides a "reliable byte stream" and knows nothing about HTTP. The HTTP message format (GET / HTTP/1.1\r\n) is the Application Layer's responsibility.
The OS actually creates packets, but to understand the concept, let's make a "fake packet" in Python.
# Simulate each layer adding headers
def application_layer(data):
"""Application Layer: Generate HTTP request"""
http_request = f"GET /api/users HTTP/1.1\r\nHost: api.example.com\r\n\r\n{data}"
print(f"[Application] Data: {http_request[:50]}...")
return http_request
def transport_layer(data):
"""Transport Layer: Add TCP header"""
tcp_header = "[TCP: SRC=5000 DST=443 SEQ=1000]"
segment = tcp_header + data
print(f"[Transport] Segment: {segment[:60]}...")
return segment
def internet_layer(data):
"""Internet Layer: Add IP header"""
ip_header = "[IP: SRC=192.168.0.10 DST=93.184.216.34]"
packet = ip_header + data
print(f"[Internet] Packet: {packet[:70]}...")
return packet
def network_interface_layer(data):
"""Network Interface Layer: Add Ethernet header"""
eth_header = "[ETH: SRC_MAC=AA:BB:CC DST_MAC=11:22:33]"
frame = eth_header + data
print(f"[Network Interface] Frame: {frame[:80]}...")
return frame
# Execute
original_data = "user_id=123"
app_data = application_layer(original_data)
transport_data = transport_layer(app_data)
internet_data = internet_layer(transport_data)
final_frame = network_interface_layer(internet_data)
print("\nFinal transmission data:")
print(final_frame[:100] + "...")
Output:
[Application] Data: GET /api/users HTTP/1.1
Host: api.example.com...
[Transport] Segment: [TCP: SRC=5000 DST=443 SEQ=1000]GET /api/users HTTP/1.1...
[Internet] Packet: [IP: SRC=192.168.0.10 DST=93.184.216.34][TCP: SRC=5000 DST=...
[Network Interface] Frame: [ETH: SRC_MAC=AA:BB:CC DST_MAC=11:22:33][IP: SRC=192.168.0.10 DST=...
Final transmission data:
[ETH: SRC_MAC=AA:BB:CC DST_MAC=11:22:33][IP: SRC=192.168.0.10 DST=93.184.216.34][TCP: SRC=5000...
Each function represents one layer, and as it goes from top to bottom, headers get progressively added. In reality, it's binary format, but the concept is identical.
Theory alone doesn't make it tangible, so let's capture actual packets. Install Wireshark (packet analysis tool), enable capture, and run curl https://example.com. You'll see a structure like this:
Frame 1: 66 bytes on wire
Ethernet II
Destination: 11:22:33:44:55:66
Source: AA:BB:CC:DD:EE:FF
Type: IPv4 (0x0800)
Internet Protocol Version 4
Source: 192.168.0.10
Destination: 93.184.216.34
Protocol: TCP (6)
Transmission Control Protocol
Source Port: 54321
Destination Port: 443
Flags: SYN
[Application Data: TLS Client Hello]
The four layers are clearly separated in reality.
In Wireshark, you can expand each layer to see every header field (TTL, Sequence Number, Checksum, etc.). This is "theory from textbooks" actually working in practice.
Each layer is independent, so you can swap one layer without affecting the rest.
Application developers don't need to know how TCP handles retransmission. They just use the interface: "send it and trust it arrives." Similarly, TCP developers don't need to know how IP routes, and IP developers don't need to know how Ethernet sends electrical signals.
Standard protocols exist for each layer, so equipment from different companies can interoperate. Apple laptops, Samsung smartphones, and Cisco routers all follow TCP/IP, so they can communicate.
If TCP/IP 4 layers are what's used in practice, why do schools still teach OSI 7 layers?
Simple answer: OSI is better for conceptual understanding.
OSI breaks down each layer's role more granularly. Separating Session Layer (connection management), Presentation Layer (data format conversion), and Application Layer (actual application logic) makes it easier to answer questions like "Where does encryption happen?" or "Who manages connection state?"
Also, among network engineers, terms like "Layer 3 switch" and "Layer 7 load balancer" are common. These refer to OSI layers. So knowing both models reduces confusion in real-world conversations.
Bottom line: OSI is a model for learning, TCP/IP is a model for doing.
graph LR
subgraph OSI["OSI 7 Layers"]
O7[7. Application]
O6[6. Presentation]
O5[5. Session]
O4[4. Transport]
O3[3. Network]
O2[2. Data Link]
O1[1. Physical]
end
subgraph TCP["TCP/IP 4 Layers"]
T4[4. Application]
T3[3. Transport]
T2[2. Internet]
T1[1. Network Interface]
end
O7 --> T4
O6 --> T4
O5 --> T4
O4 --> T3
O3 --> T2
O2 --> T1
O1 --> T1
OSI layers 5, 6, 7 merged into TCP/IP's Application Layer, and OSI layers 1, 2 merged into TCP/IP's Network Interface Layer. The middle layers (Transport, Network/Internet) are nearly identical.
After understanding the TCP/IP 4-layer model, all the concepts I vaguely used before finally connected.
And when I type curl, I can now visualize my data sequentially traversing four layers, getting "wrapped," crossing the Internet, and getting "unwrapped" at the server.
The core principles were layering and encapsulation. Each layer does its job, treats upper-layer data as "cargo," and adds its own header. This simple principle powers the entire Internet.
I thought OSI 7 layers were only for exams, but they're still useful for conceptual understanding. However, when writing code and analyzing packets, TCP/IP 4 layers are far more intuitive. This was my moment of understanding the difference between theory and practice.