Sockets – Fundamentals of TCP/IP Networks

 

Chapter 58: Sockets – Fundamentals of TCP/IP Networks
Part 2 of 3  |  Protocol Layers, Transparency & Encapsulation
🏗 Layered Model
📦 Encapsulation
🔍 Transparency

This part explains how TCP/IP is organized into layers, why that layered design is so powerful, and how data is wrapped (encapsulated) as it travels from your application down to the physical wire. This is foundational knowledge for anyone writing socket programs or debugging network issues.

Key Terms
networking protocol protocol layers protocol stack TCP UDP IP SOCK_STREAM SOCK_DGRAM SOCK_RAW transparency encapsulation header segment datagram ARP ICMP IGMP

1. What is a Networking Protocol?

A networking protocol is a set of rules that define how information is formatted and transmitted across a network. Two machines that both follow the same protocol can exchange data correctly — regardless of their hardware or operating system.

Protocols are organized into layers. Each layer does a specific job and provides services to the layer above it, while using services from the layer below it. This is called a layered architecture or protocol stack.

Why layers? Layers let you change one part of the network without affecting everything else. Wi-Fi replacing Ethernet at the bottom layer does not break TCP at the top layer. Each layer only needs to know the interface to the layer below it.

2. The TCP/IP Protocol Stack (Four Layers)

The TCP/IP suite is organized into four layers. From top to bottom:

TCP/IP Protocol Stack

USER SPACE
Application Layer
Your program: HTTP client, SSH, custom socket app
Socket types: SOCK_STREAM  |  SOCK_DGRAM  |  SOCK_RAW
KERNEL
Transport Layer
TCP (reliable stream)  |  UDP (unreliable datagram)
Network Layer (Internet Layer)
IP — routes packets across networks
Data-Link Layer
Network interface hardware (Ethernet, Wi-Fi card)
Physical Medium
Cable, fiber optic, radio waves (Wi-Fi)

The code implementing all these layers together is called the protocol stack. On Linux, the kernel contains the TCP, UDP, and IP implementations. The data-link layer is implemented in device drivers and network interface hardware.

Why is it called TCP/IP? Because TCP is the most heavily used transport-layer protocol. When people say “TCP/IP”, they mean the entire family — TCP, UDP, IP, and all supporting protocols.

3. Supporting Protocols: ARP, ICMP, IGMP

The TCP/IP suite includes several supporting protocols beyond TCP, UDP, and IP:

Protocol Full Name Purpose Used By
ARP Address Resolution Protocol Maps IP addresses to hardware (MAC) addresses Kernel, automatically
ICMP Internet Control Message Protocol Conveys error and control information between hosts ping, traceroute
IGMP Internet Group Management Protocol Manages IP multicast group membership Multicast applications
ping uses ICMP: When you run ping 8.8.8.8, the kernel sends an ICMP Echo Request packet and waits for an ICMP Echo Reply. If the host is alive and reachable, you get a reply. This operates below TCP/UDP — at the IP/ICMP level.

4. Transparency — Why Layers Are Powerful

Transparency means each layer hides its internal complexity from the layers above it. A higher layer only sees a clean interface — not the messy details underneath.

Transparency in Action
Application (Your Code)
“I just want to send bytes to a remote address. I don’t care how.”
TCP Layer (Kernel)
“I handle reliability, ordering, flow control. App doesn’t see this.”
IP Layer (Kernel)
“I handle routing between networks. TCP doesn’t see this.”
Data-Link Layer (Driver)
“I handle frames on the wire. IP doesn’t see this.”
What transparency gives you:

  • Your app works over Ethernet, Wi-Fi, fiber — without any changes to your code
  • You can swap UDP for TCP with minimal code change
  • The kernel handles packet loss, retransmit, routing — your code just reads/writes
  • New physical technologies can be added at the data-link layer without rewriting TCP or your app
From the application’s perspective: When two socket applications on different machines communicate via TCP, it looks as though they are connected directly to each other. The application sees a simple byte stream — the TCP layer, IP layer, and data-link layer are all invisible.

5. Encapsulation — How Data Travels Down and Up the Stack

Encapsulation is how data passes down through protocol layers. Each layer treats the data from the layer above it as an opaque blob — it does not try to interpret it. Instead, it wraps the blob in its own packet format by adding a header (and sometimes a trailer), then passes the wrapped packet to the layer below.

Encapsulation: Sender Side (top → bottom)
Application Data
e.g., “GET /index.html HTTP/1.1\r\n…”
↓ TCP adds header (port numbers, sequence numbers, flags)
TCP Header
Application Data
= TCP Segment
↓ IP adds header (source IP, destination IP, TTL)
IP Header
TCP Header
Application Data
= IP Datagram
↓ Data-link adds frame header + trailer (MAC addresses, CRC)
Frame Hdr
IP Hdr
TCP Hdr
App Data
CRC
= Network Frame (sent over the wire)

On the receiving side, the opposite happens — each layer strips its own header and passes the inner data up to the layer above. This is called de-encapsulation.

De-encapsulation: Receiver Side (bottom → top)
Wire Frame  →  Data-link strips frame header/trailer →  IP Datagram
IP Datagram  →  IP strips IP header →  TCP Segment
TCP Segment  →  TCP strips TCP header →  Application Data
Application Data  →  Your code reads it
Key insight: Each layer treats what it receives from above as an opaque blob. IP does not look inside a TCP segment to understand it — IP just adds its own header and sends the whole thing down. This is what makes the layered design so clean and extensible.

6. Socket Types and Their Layer Relationships

When you create a socket in C, you specify a socket type that determines which transport protocol you use:

Socket Type Protocol Layer Characteristic
SOCK_STREAM TCP Transport Reliable, ordered, byte stream. Connection-oriented.
SOCK_DGRAM UDP Transport Unreliable, unordered datagrams. Connectionless.
SOCK_RAW IP (raw) Network Bypass transport layer. Construct your own headers. Requires root.

7. Code Examples: Seeing the Protocol Stack

Example 1: SOCK_STREAM (TCP) socket creation

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(void)
{
    /* AF_INET = IPv4 (network layer)
       SOCK_STREAM = TCP (transport layer)
       Protocol 0 = let kernel choose (chooses TCP for SOCK_STREAM) */
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (sockfd == -1) {
        perror("socket");
        return 1;
    }

    printf("TCP socket created. fd = %d\n", sockfd);

    /* At this point we have a socket that will use:
       Application data → TCP header → IP header → Data-link frame */

    close(sockfd);
    return 0;
}

Example 2: SOCK_DGRAM (UDP) socket creation

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(void)
{
    /* SOCK_DGRAM = UDP at transport layer
       No connection, no guarantee of delivery or ordering */
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    if (sockfd == -1) {
        perror("socket");
        return 1;
    }

    printf("UDP socket created. fd = %d\n", sockfd);
    close(sockfd);
    return 0;
}

Example 3: SOCK_RAW — bypass transport layer, access IP directly (requires root)

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(void)
{
    /* SOCK_RAW with IPPROTO_ICMP:
       Lets us send/receive raw ICMP packets — like ping does.
       We must construct the ICMP header ourselves.
       Requires root privileges (or CAP_NET_RAW capability). */
    int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

    if (sockfd == -1) {
        perror("socket (need root for SOCK_RAW)");
        return 1;
    }

    printf("Raw ICMP socket created. fd = %d\n", sockfd);
    close(sockfd);
    return 0;
}

Example 4: Use tcpdump to watch encapsulation in action

# In terminal 1 — capture packets on loopback interface
sudo tcpdump -i lo -vv -X port 8080

# In terminal 2 — send a quick TCP connection
nc 127.0.0.1 8080

# tcpdump output shows you:
# 1. The Ethernet frame header (data-link layer)
# 2. The IP datagram header (network layer: src IP, dst IP, TTL)
# 3. The TCP segment header (transport layer: src port, dst port, seq, ack)
# 4. The payload (application data)
# This is encapsulation visible in real time!

Example 5: Read IP header fields from a raw socket (shows encapsulation structure)

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>   /* struct iphdr */
#include <arpa/inet.h>
#include <string.h>

int main(void)
{
    char buf[65536];
    struct sockaddr_in saddr;
    socklen_t saddr_len = sizeof(saddr);

    /* Raw socket — capture all IP packets coming in */
    int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    if (sockfd < 0) {
        perror("socket (need root)");
        return 1;
    }

    printf("Listening for TCP packets (IP header visible)...\n");

    /* Receive one packet */
    int n = recvfrom(sockfd, buf, sizeof(buf), 0,
                     (struct sockaddr *)&saddr, &saddr_len);
    if (n < 0) { perror("recvfrom"); return 1; }

    /* Cast beginning of buffer to IP header */
    struct iphdr *iph = (struct iphdr *)buf;

    char src[INET_ADDRSTRLEN], dst[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &iph->saddr, src, sizeof(src));
    inet_ntop(AF_INET, &iph->daddr, dst, sizeof(dst));

    printf("IP Header:\n");
    printf("  Version   : %d\n", iph->version);
    printf("  IHL       : %d bytes\n", iph->ihl * 4);
    printf("  TTL       : %d\n", iph->ttl);
    printf("  Protocol  : %d (6=TCP, 17=UDP, 1=ICMP)\n", iph->protocol);
    printf("  Src IP    : %s\n", src);
    printf("  Dst IP    : %s\n", dst);
    printf("  Total Len : %d bytes (IP hdr + TCP hdr + data)\n",
           ntohs(iph->tot_len));

    close(sockfd);
    return 0;
}
/* Compile: gcc -o raw_ip raw_ip.c
   Run:     sudo ./raw_ip     */

Interview Questions
Q1. What is a protocol stack and why does TCP/IP use a layered design?
Answer: A protocol stack is the combined implementation of all TCP/IP layers: application, transport (TCP/UDP), network (IP), and data-link. A layered design is used because it separates concerns — each layer has one job, hides its complexity from layers above it, and can be changed independently. You can upgrade the physical network (e.g., from copper to fiber) without touching TCP.
Q2. What does “transparency” mean in the context of protocol layers?
Answer: Transparency means each layer hides its operations from the layers above it. An application using TCP only needs to know it gets a reliable byte stream — it does not need to understand how TCP achieves reliability (retransmission, sequence numbers, etc.). Similarly, TCP does not see the details of IP routing, and IP does not see the details of Ethernet framing.
Q3. Explain encapsulation with an example of sending an HTTP request.
Answer: The application produces HTTP data (“GET /index.html…”). TCP wraps it with a TCP header (adding port numbers, sequence number) → this becomes a TCP segment. IP wraps the segment with an IP header (source/dest IP, TTL) → this becomes an IP datagram. The data-link layer wraps the datagram in a frame (MAC addresses, CRC) → this is sent over the wire. At each step, the lower layer treats the upper-layer data as an opaque blob and does not interpret it.
Q4. What is the difference between SOCK_STREAM, SOCK_DGRAM, and SOCK_RAW?
Answer: SOCK_STREAM uses TCP — reliable, ordered, connection-oriented byte stream. SOCK_DGRAM uses UDP — unreliable, connectionless datagrams. SOCK_RAW bypasses the transport layer entirely, giving you direct access to the IP layer so you can construct your own protocol headers (used by ping, traceroute, custom protocol tools; requires root).
Q5. What is the role of ICMP? How is it different from TCP and UDP?
Answer: ICMP (Internet Control Message Protocol) carries error and control messages — for example, “destination unreachable” or “time exceeded”. It is not a transport protocol for application data; it operates at the same level as IP. TCP and UDP carry application data between ports. ICMP is used by diagnostic tools: ping sends ICMP Echo Request/Reply; traceroute uses ICMP Time Exceeded messages.
Q6. What does ARP do and at what layer does it operate?
Answer: ARP (Address Resolution Protocol) maps an IP address (network layer) to a hardware MAC address (data-link layer). When your machine knows the destination IP but needs to know the destination MAC address to send an Ethernet frame, it broadcasts an ARP request: “Who has IP 192.168.1.5? Tell me your MAC address.” The target replies with its MAC. ARP operates between the network and data-link layers.
Q7. Why does an application not need to know whether it is running over Ethernet or Wi-Fi?
Answer: Because of transparency and encapsulation. The data-link layer handles everything specific to Ethernet or Wi-Fi — framing, MAC addressing, collision detection, etc. The IP layer above it only sees the datagram it needs to send, not the physical medium. TCP above IP only sees a network that can deliver datagrams. The application only sees a socket API. Each layer completely hides the lower layer’s details.
Q8. What unit of data is produced at each TCP/IP layer?
Answer: Application layer → application message/data. TCP (transport) layer → segment. IP (network) layer → datagram. Data-link layer → frame. Physical layer → bits on the wire.

Leave a Reply

Your email address will not be published. Required fields are marked *