TCP/IP Protocol Stack Explained

The TCP/IP protocol stack is the fundamental framework that enables communication across the Internet and most modern networks. Understanding how data flows through these protocol layers is essential for network engineers, developers, and IT professionals. This comprehensive guide explores each layer of the TCP/IP model, explaining how protocols work together to enable reliable data transmission.

The TCP/IP Model

The TCP/IP model consists of four layers, each with specific responsibilities:

┌─────────────────────────────┐
│   Application Layer         │  HTTP, FTP, SSH, DNS, SMTP
├─────────────────────────────┤
│   Transport Layer           │  TCP, UDP
├─────────────────────────────┤
│   Internet Layer            │  IP, ICMP, ARP
├─────────────────────────────┤
│   Link Layer               │  Ethernet, Wi-Fi, PPP
└─────────────────────────────┘

TCP/IP vs OSI Model

OSI Model              TCP/IP Model
─────────────          ────────────
Application    ┐
Presentation   │  →    Application
Session        ┘
Transport      →       Transport
Network        →       Internet
Data Link      ┐  →    Link
Physical       ┘

The Link Layer handles physical transmission of data over network media.

Responsibilities

  • Physical addressing (MAC addresses)
  • Frame formatting
  • Error detection (not correction)
  • Media access control

Ethernet Frame Structure

Preamble (7 bytes) + SFD (1 byte)
┌────────────────────────────────────────────────┐
│ Destination MAC │ Source MAC │ Type │ Data │ FCS │
│    6 bytes      │  6 bytes   │2 bytes│      │4 bytes│
└────────────────────────────────────────────────┘

Type/EtherType values:
0x0800 = IPv4
0x0806 = ARP
0x86DD = IPv6

MAC Addresses

48-bit addresses in hexadecimal format:

Example: 00:1A:2B:3C:4D:5E

Structure:
┌──────────────────┬──────────────────┐
│  OUI (24 bits)   │  NIC (24 bits)   │
│ Manufacturer ID  │  Device Specific │
└──────────────────┴──────────────────┘

Special addresses:
FF:FF:FF:FF:FF:FF = Broadcast
01:00:5E:xx:xx:xx = IPv4 Multicast
33:33:xx:xx:xx:xx = IPv6 Multicast

ARP (Address Resolution Protocol)

Maps IP addresses to MAC addresses:

ARP Request (Broadcast):
Who has 192.168.1.1? Tell 192.168.1.100

ARP Reply (Unicast):
192.168.1.1 is at AA:BB:CC:DD:EE:FF

ARP packet structure:

┌──────────────────────────────────────┐
│ Hardware Type (2)  │ Protocol Type (2)│
├────────────────────┼──────────────────┤
│ HW Addr Len (1)    │ Proto Addr Len(1)│
├──────────────────────────────────────┤
│         Operation (2)                 │
├──────────────────────────────────────┤
│    Sender Hardware Address (6)        │
├──────────────────────────────────────┤
│    Sender Protocol Address (4)        │
├──────────────────────────────────────┤
│    Target Hardware Address (6)        │
├──────────────────────────────────────┤
│    Target Protocol Address (4)        │
└──────────────────────────────────────┘

Example ARP operations:

# View ARP cache
arp -a

## Windows
arp -a

## Linux
ip neigh show

## Clear ARP cache
sudo ip neigh flush all

Internet Layer (Network Layer)

The Internet Layer handles logical addressing and routing.

IPv4 (Internet Protocol version 4)

IPv4 Header Structure

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
┌───────┬───────┬───────────────┬───────────────────────────────┐
│Version│  IHL  │     DSCP/ToS  │        Total Length           │
├───────┴───────┴───────────────┼───────────────┬───────────────┤
│         Identification        │ Flags │   Fragment Offset     │
├───────────────┬───────────────┼───────────────┴───────────────┤
│      TTL      │   Protocol    │       Header Checksum         │
├───────────────┴───────────────┴───────────────────────────────┤
│                      Source IP Address                         │
├────────────────────────────────────────────────────────────────┤
│                   Destination IP Address                       │
├────────────────────────────────────────────────────────────────┤
│                    Options (if IHL > 5)                        │
└────────────────────────────────────────────────────────────────┘

Key Fields:

  • Version: 4 (for IPv4)
  • IHL: Header length in 32-bit words (minimum 5)
  • DSCP: Differentiated Services Code Point (QoS)
  • Total Length: Entire packet size (max 65,535 bytes)
  • TTL: Time To Live (hop count, max 255)
  • Protocol: Upper layer protocol (TCP=6, UDP=17, ICMP=1)

IPv4 Addressing

Address Classes (Historical):
Class A: 0.0.0.0     - 127.255.255.255  (/8)
Class B: 128.0.0.0   - 191.255.255.255  (/16)
Class C: 192.0.0.0   - 223.255.255.255  (/24)
Class D: 224.0.0.0   - 239.255.255.255  (Multicast)
Class E: 240.0.0.0   - 255.255.255.255  (Reserved)

Private IP Ranges (RFC 1918):
10.0.0.0/8        (10.0.0.0 - 10.255.255.255)
172.16.0.0/12     (172.16.0.0 - 172.31.255.255)
192.168.0.0/16    (192.168.0.0 - 192.168.255.255)

Special Addresses:
0.0.0.0           - This network
127.0.0.0/8       - Loopback
169.254.0.0/16    - Link-local (APIPA)
255.255.255.255   - Broadcast

Subnet Masking

Example: 192.168.1.0/24

Binary representation:
IP:      11000000.10101000.00000001.00000000
Mask:    11111111.11111111.11111111.00000000
Network: 11000000.10101000.00000001.00000000

CIDR Notation:
/24 = 255.255.255.0   (254 hosts)
/25 = 255.255.255.128 (126 hosts)
/26 = 255.255.255.192 (62 hosts)
/27 = 255.255.255.224 (30 hosts)
/28 = 255.255.255.240 (14 hosts)
/29 = 255.255.255.248 (6 hosts)
/30 = 255.255.255.252 (2 hosts)
/31 = 255.255.255.254 (2 hosts, point-to-point)
/32 = 255.255.255.255 (1 host)

Calculating subnet information:

def calculate_subnet(ip, cidr):
    # Example: 192.168.1.100/24
    octets = [int(x) for x in ip.split('.')]
    
    # Calculate mask
    mask_bits = int(cidr)
    mask = [0, 0, 0, 0]
    for i in range(4):
        if mask_bits >= 8:
            mask[i] = 255
            mask_bits -= 8
        else:
            mask[i] = 256 - (2 ** (8 - mask_bits))
            mask_bits = 0
    
    # Network address
    network = [octets[i] & mask[i] for i in range(4)]
    
    # Broadcast address
    broadcast = [network[i] | (255 - mask[i]) for i in range(4)]
    
    # First and last usable
    first = network.copy()
    first[3] += 1
    last = broadcast.copy()
    last[3] -= 1
    
    return {
        'network': '.'.join(map(str, network)),
        'broadcast': '.'.join(map(str, broadcast)),
        'first_usable': '.'.join(map(str, first)),
        'last_usable': '.'.join(map(str, last)),
        'total_hosts': 2 ** (32 - int(cidr)) - 2
    }

IPv6 (Internet Protocol version 6)

IPv6 Header Structure

Simplified compared to IPv4:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
┌───────┬───────────────────┬───────────────────────────────────┐
│Version│ Traffic Class     │        Flow Label                 │
├───────┴───────────────────┴───────────────┬───────────────────┤
│         Payload Length                    │  Next Header      │
├───────────────────────────────────────────┴───────────────────┤
│                    Hop Limit                                   │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│                   Source Address (128 bits)                    │
│                                                                │
│                                                                │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│                 Destination Address (128 bits)                 │
│                                                                │
│                                                                │
└────────────────────────────────────────────────────────────────┘

IPv6 Addressing

Address Format:
2001:0db8:85a3:0000:0000:8a2e:0370:7334

Abbreviation rules:
1. Leading zeros can be omitted
   2001:0db8:85a3:0:0:8a2e:0370:7334

2. Consecutive zero groups replaced with ::
   2001:db8:85a3::8a2e:370:7334

Address Types:
Global Unicast:    2000::/3
Link-Local:        fe80::/10
Unique Local:      fc00::/7
Multicast:         ff00::/8
Loopback:          ::1/128
Unspecified:       ::/128

Common Prefixes:
/32  - ISP allocation
/48  - Site allocation
/64  - Subnet (standard)
/128 - Single host

ICMP (Internet Control Message Protocol)

Used for diagnostic and error reporting:

Common ICMP Types:
0  - Echo Reply (ping response)
3  - Destination Unreachable
   0: Network Unreachable
   1: Host Unreachable
   3: Port Unreachable
   4: Fragmentation Needed
5  - Redirect
8  - Echo Request (ping)
11 - Time Exceeded
   0: TTL Exceeded

Ping example:

## Standard ping
ping 8.8.8.8

## Set packet size
ping -s 1024 8.8.8.8

## Set TTL
ping -t 10 8.8.8.8

## Continuous ping with timestamp
ping 8.8.8.8 | while read line; do echo "$(date '+%T') - $line"; done

Traceroute using ICMP:

## Linux
traceroute google.com

## Windows
tracert google.com

## How it works:
## Send packets with increasing TTL
## TTL=1: First hop responds with ICMP Time Exceeded
## TTL=2: Second hop responds with ICMP Time Exceeded
## Continue until destination reached

Transport Layer

The Transport Layer provides end-to-end communication services.

TCP (Transmission Control Protocol)

Connection-oriented, reliable protocol.

TCP Header Structure

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
┌───────────────────────────────┬───────────────────────────────┐
│         Source Port           │      Destination Port         │
├───────────────────────────────┴───────────────────────────────┤
│                      Sequence Number                           │
├────────────────────────────────────────────────────────────────┤
│                   Acknowledgment Number                        │
├─────┬─────┬─┬─┬─┬─┬─┬─┬───────────────────────────────────────┤
│Data │ Res │N│C│E│U│A│P│R│S│F│         Window Size             │
│Offset│     │S│W│C│R│C│S│S│Y│I│                                 │
├─────┴─────┴─┴─┴─┴─┴─┴─┴─┴─┴─┴───────────────────────────────┤
│           Checksum            │       Urgent Pointer          │
├───────────────────────────────┴───────────────────────────────┤
│                    Options (if Data Offset > 5)                │
└────────────────────────────────────────────────────────────────┘

TCP Flags:

  • SYN: Synchronize sequence numbers (connection establishment)
  • ACK: Acknowledgment field is valid
  • FIN: Finish, no more data (connection termination)
  • RST: Reset connection
  • PSH: Push data to application immediately
  • URG: Urgent pointer field is valid

TCP Three-Way Handshake

Connection establishment:

Client                          Server
  │                               │
  │───────── SYN ────────────────>│
  │    SEQ=1000                   │
  │                               │
  │<──── SYN-ACK ─────────────────│
  │    SEQ=2000, ACK=1001         │
  │                               │
  │───────── ACK ────────────────>│
  │    SEQ=1001, ACK=2001         │
  │                               │
  │    Connection Established     │

Example using Python:

import socket

## Server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 8080))
server.listen(1)
print("Waiting for connection...")
conn, addr = server.accept()
print(f"Connected to {addr}")

## Client
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 8080))
print("Connected to server")

TCP Connection Termination

Four-way handshake:

Client                          Server
  │                               │
  │───────── FIN ────────────────>│
  │    SEQ=5000                   │
  │                               │
  │<──────── ACK ─────────────────│
  │    ACK=5001                   │
  │                               │
  │<──────── FIN ─────────────────│
  │    SEQ=6000                   │
  │                               │
  │───────── ACK ────────────────>│
  │    ACK=6001                   │
  │                               │
  │    Connection Closed          │

TCP Flow Control

Sliding window mechanism:

Sender Window:
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ Sent│ Sent│ Can │ Can │Can't│Can't│Can't│Can't│
│ ACKd│Wait │ Send│ Send│ Send│ Send│ Send│ Send│
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
         ↑         Window Size

Window Advertisement:
ACK packet includes window size field
Tells sender how much data receiver can accept

Python example of TCP with flow control:

import socket

## Configure socket buffer sizes
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)

## Get current buffer sizes
recv_buf = sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
send_buf = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
print(f"Receive buffer: {recv_buf}, Send buffer: {send_buf}")

TCP Congestion Control

Algorithms to prevent network congestion:

1. Slow Start
   - Start with small congestion window (cwnd)
   - Double cwnd each RTT until threshold
   
2. Congestion Avoidance
   - Increase cwnd by 1 MSS per RTT
   - Linear growth
   
3. Fast Retransmit
   - Retransmit on 3 duplicate ACKs
   - Don't wait for timeout
   
4. Fast Recovery
   - Continue data flow after fast retransmit
   - Avoid slow start

UDP (User Datagram Protocol)

Connectionless, unreliable protocol.

UDP Header Structure

Much simpler than TCP:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
┌───────────────────────────────┬───────────────────────────────┐
│         Source Port           │      Destination Port         │
├───────────────────────────────┴───────────────────────────────┤
│            Length             │           Checksum            │
└───────────────────────────────┴───────────────────────────────┘

UDP example:

import socket

## UDP Server
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('0.0.0.0', 9999))
print("UDP server listening...")
data, addr = server.recvfrom(1024)
print(f"Received from {addr}: {data.decode()}")

## UDP Client
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(b"Hello UDP!", ('localhost', 9999))

TCP vs UDP Comparison

Feature          TCP              UDP
───────────────  ───────────────  ──────────────
Connection       Yes              No
Reliability      Guaranteed       Best effort
Ordering         Guaranteed       Not guaranteed
Speed            Slower           Faster
Overhead         Higher           Lower
Use Cases        Web, Email, FTP  DNS, Video, VoIP
Header Size      20-60 bytes      8 bytes

Application Layer

The Application Layer protocols enable specific services.

DNS (Domain Name System)

DNS Query Structure:
┌────────────────────────────────┐
│          Header                 │
│  Transaction ID, Flags, Counts │
├────────────────────────────────┤
│          Question              │
│  Name, Type, Class             │
├────────────────────────────────┤
│          Answer                │
│  Name, Type, Class, TTL, Data  │
├────────────────────────────────┤
│         Authority              │
├────────────────────────────────┤
│         Additional             │
└────────────────────────────────┘

Record Types:
A     - IPv4 address
AAAA  - IPv6 address
CNAME - Canonical name (alias)
MX    - Mail exchange
NS    - Name server
PTR   - Pointer (reverse DNS)
SOA   - Start of authority
TXT   - Text record

DNS lookup example:

## Query A record
dig example.com A

## Query with specific DNS server
dig @8.8.8.8 example.com

## Trace [DNS resolution](https://terabyte.systems/posts/how-to-fix-dns-resolution-issues/)
dig +trace example.com

## Reverse DNS lookup
dig -x 8.8.8.8

HTTP (Hypertext Transfer Protocol)

HTTP Request:
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html
Connection: keep-alive

HTTP Response:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
Server: Apache/2.4.41

<html>...</html>

HTTP methods:

GET     - Retrieve resource
POST    - Submit data
PUT     - Update resource
DELETE  - Remove resource
HEAD    - Get headers only
OPTIONS - Get supported methods
PATCH   - Partial update

Port Numbers

Well-known ports (0-1023):

Port    Protocol    Service
────    ────────    ───────
20/21   TCP         FTP (data/control)
22      TCP         SSH
23      TCP         Telnet
25      TCP         SMTP
53      TCP/UDP     DNS
67/68   UDP         DHCP
80      TCP         HTTP
110     TCP         POP3
143     TCP         IMAP
443     TCP         HTTPS
3389    TCP         RDP
3306    TCP         MySQL
5432    TCP         PostgreSQL
6379    TCP         Redis
27017   TCP         MongoDB

Packet Flow Example

Complete packet flow from application to wire:

1. Application Layer (HTTP)
   ┌────────────────────────────┐
   │ GET /index.html HTTP/1.1   │
   └────────────────────────────┘

2. Transport Layer (TCP)
   ┌────────────────────────────┐
   │ TCP Header (Src:52341     │
   │ Dst:80)                    │
   ├────────────────────────────┤
   │ HTTP Data                  │
   └────────────────────────────┘

3. Internet Layer (IP)
   ┌────────────────────────────┐
   │ IP Header (Src:192.168.1.2│
   │ Dst:93.184.216.34)        │
   ├────────────────────────────┤
   │ TCP Segment                │
   └────────────────────────────┘

4. Link Layer (Ethernet)
   ┌────────────────────────────┐
   │ Ethernet Header            │
   │ (Src MAC, Dst MAC)        │
   ├────────────────────────────┤
   │ IP Packet                  │
   ├────────────────────────────┤
   │ FCS (Checksum)            │
   └────────────────────────────┘

5. Physical Layer
   01010101010101... (bits on wire)

Troubleshooting Tools

## View network interfaces
ip addr show          # Linux
ifconfig              # Linux/macOS
ipconfig /all         # Windows

## View routing table
ip route show         # Linux
route print           # Windows
netstat -rn           # Linux/macOS

## Packet capture
sudo tcpdump -i eth0 -w capture.pcap
sudo tcpdump -i eth0 host 8.8.8.8
sudo tcpdump -i eth0 port 80

## Network statistics
netstat -s            # All statistics
ss -s                 # Socket statistics (Linux)
netstat -an           # All connections

## Test connectivity
ping 8.8.8.8          # ICMP echo
nc -zv host 80        # TCP port test
telnet host 80        # Interactive TCP

Conclusion

The TCP/IP protocol stack is the foundation of modern networking. Understanding how data flows through each layer—from application requests down to physical bits on the wire—is crucial for:

  • Debugging network issues
  • Optimizing network performance
  • Implementing security measures
  • Designing scalable applications
  • Understanding network behavior

Key concepts:

  • Encapsulation: Each layer adds its header
  • Abstraction: Each layer provides services to the layer above
  • Modularity: Layers can be updated independently
  • Interoperability: Standard protocols enable diverse systems to communicate

The elegance of TCP/IP lies in its simplicity and flexibility, enabling everything from local network communication to global Internet connectivity while maintaining backward compatibility and supporting continuous innovation.

Thank you for reading! If you have any feedback or comments, please send them to [email protected].