READMEC++

README

Expert Topics / Networking

Concept Lesson
Intermediate
4 min

Learning Objective

Understand Expert Topics well enough to explain it, recognize it in C++, and apply it in a small task.

Why It Matters

This concept is part of the foundation that later lessons and projects assume you already understand.

ExpertTopicsTable Of ContentsNetwork Programming FundamentalsThe Osi And Tcp/Ip Models
Private notes
0/8000

Notes stay private to your browser until account sync is configured.

README
2 min read18 headings

Networking in C++

Network programming is file I/O with timing, failure, and protocol rules added. A socket is an endpoint; a protocol defines what bytes mean; the operating system handles the lower-level packet movement. Your C++ program is responsible for creating sockets, checking errors, sending and receiving bytes, and closing resources correctly.

Think of every network operation as unreliable by default. Connections can fail, reads can return partial data, writes can send fewer bytes than requested, and the other side can disappear at any time.

Table of Contents

  1. Network Programming Fundamentals
  2. Socket Basics
  3. TCP Client
  4. TCP Server
  5. UDP Communication
  6. Non-Blocking I/O
  7. Best Practices

Network Programming Fundamentals

The OSI and TCP/IP Models

┌──────────────────────────────────────────────────────────────────────────────┐
│                      NETWORK LAYERS OVERVIEW                                  │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                               │
│   OSI Model              TCP/IP Model         What C++ Sockets Use           │
│   ─────────              ────────────         ────────────────────           │
│                                                                               │
│  ┌─────────────┐        ┌─────────────┐                                      │
│  │ Application │        │             │       ◄── Your C++ Application       │
│  ├─────────────┤        │ Application │           HTTP, FTP, Custom Protocol │
│  │ Presentation│        │             │                                      │
│  ├─────────────┤        └─────────────┘                                      │
│  │   Session   │                                                             │
│  ├─────────────┤        ┌─────────────┐       ◄── Socket API (TCP/UDP)       │
│  │  Transport  │        │  Transport  │           SOCK_STREAM, SOCK_DGRAM    │
│  ├─────────────┤        └─────────────┘                                      │
│  │   Network   │        ┌─────────────┐       ◄── IP Addresses               │
│  ├─────────────┤        │   Network   │           AF_INET, AF_INET6          │
│  │  Data Link  │        └─────────────┘                                      │
│  ├─────────────┤        ┌─────────────┐       ◄── Handled by OS              │
│  │  Physical   │        │Network Iface│                                      │
│  └─────────────┘        └─────────────┘                                      │
│                                                                               │
└──────────────────────────────────────────────────────────────────────────────┘

TCP vs UDP Comparison

┌─────────────────────────────────────────────────────────────────────────────┐
│                         TCP vs UDP COMPARISON                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  TCP (Transmission Control Protocol)     UDP (User Datagram Protocol)       │
│  ────────────────────────────────────    ────────────────────────────       │
│                                                                              │
│   ┌───────────┐     Connection?     ┌───────────┐                           │
│   │  Client   │◄────────────────────│  Server   │                           │
│   └─────┬─────┘    Established!     └─────┬─────┘                           │
│         │                                 │                                  │
│         │──── Data packet 1 ─────────────►│                                  │
│         │◄─── ACK ────────────────────────│                                  │
│         │──── Data packet 2 ─────────────►│                                  │
│         │◄─── ACK ────────────────────────│                                  │
│                                                                              │
│   ✅ Reliable (guaranteed delivery)    ❌ No guarantee                      │
│   ✅ Ordered (packets arrive in order) ❌ May arrive out of order           │
│   ✅ Error checked                     ✅ Error checked                     │
│   ❌ Slower (overhead)                 ✅ Faster (minimal overhead)         │
│   ❌ Connection required               ✅ Connectionless                    │
│                                                                              │
│   Use for:                             Use for:                              │
│   • Web (HTTP/HTTPS)                   • Video streaming                     │
│   • Email (SMTP)                       • Online gaming                       │
│   • File transfer (FTP)                • DNS queries                         │
│   • Database connections               • VoIP                                │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Client-Server Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                     CLIENT-SERVER COMMUNICATION FLOW                         │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│        CLIENT                                        SERVER                  │
│   ┌─────────────────┐                          ┌─────────────────┐          │
│   │                 │                          │                 │          │
│   │  1. socket()    │                          │  1. socket()    │          │
│   │     Create      │                          │     Create      │          │
│   │                 │                          │                 │          │
│   └────────┬────────┘                          │  2. bind()      │          │
│            │                                   │     Assign port │          │
│            │                                   │                 │          │
│            │                                   │  3. listen()    │          │
│            │                                   │     Wait for    │          │
│            │                                   │     connections │          │
│            │                                   └────────┬────────┘          │
│            │                                            │                   │
│   ┌────────┴────────┐                          ┌────────┴────────┐          │
│   │  2. connect()   │ ─── TCP Handshake ────►  │  4. accept()    │          │
│   │     Connect to  │ ◄──────────────────────  │     Accept      │          │
│   │     server      │                          │     connection  │          │
│   └────────┬────────┘                          └────────┬────────┘          │
│            │                                            │                   │
│   ┌────────┴────────┐                          ┌────────┴────────┐          │
│   │  3. send()      │ ──── Request ─────────►  │  5. recv()      │          │
│   │     Send data   │                          │     Receive     │          │
│   └────────┬────────┘                          └────────┬────────┘          │
│            │                                            │                   │
│   ┌────────┴────────┐                          ┌────────┴────────┐          │
│   │  4. recv()      │ ◄─── Response ──────────  │  6. send()      │          │
│   │     Receive     │                          │     Send reply  │          │
│   └────────┬────────┘                          └────────┬────────┘          │
│            │                                            │                   │
│   ┌────────┴────────┐                          ┌────────┴────────┐          │
│   │  5. close()     │ ◄── Connection Close ──► │  7. close()     │          │
│   │     Close       │                          │     Close       │          │
│   └─────────────────┘                          └─────────────────┘          │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Socket Basics

A socket is an endpoint for communication - like a phone number for your program.

Required Headers (Linux/Unix)

#include <sys/socket.h>   // socket(), bind(), listen(), accept(), connect()
#include <netinet/in.h>   // sockaddr_in, INADDR_ANY
#include <arpa/inet.h>    // inet_pton(), inet_ntop(), htons()
#include <unistd.h>       // close()
#include <netdb.h>        // getaddrinfo(), gethostbyname()
#include <cstring>        // memset()

Socket Types

// AF = Address Family, SOCK = Socket type

// TCP Socket (Stream) - Reliable, ordered, connection-based
int tcpSocket = socket(AF_INET, SOCK_STREAM, 0);

// UDP Socket (Datagram) - Fast, connectionless, no guarantees
int udpSocket = socket(AF_INET, SOCK_DGRAM, 0);

// IPv6 variants
int ipv6TcpSocket = socket(AF_INET6, SOCK_STREAM, 0);
int ipv6UdpSocket = socket(AF_INET6, SOCK_DGRAM, 0);

Socket Creation Diagram

┌─────────────────────────────────────────────────────────────────────────────┐
│                        SOCKET CREATION PARAMETERS                            │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  socket(domain, type, protocol)                                              │
│          │       │      │                                                    │
│          │       │      └── Usually 0 (auto-select based on type)           │
│          │       │                                                           │
│          │       └── SOCK_STREAM ─── TCP (reliable, ordered)                │
│          │           SOCK_DGRAM ──── UDP (fast, no guarantees)              │
│          │           SOCK_RAW ────── Raw IP (advanced)                      │
│          │                                                                   │
│          └── AF_INET ─────── IPv4 (192.168.1.1)                             │
│              AF_INET6 ────── IPv6 (2001:db8::1)                             │
│              AF_UNIX ─────── Local (file-based IPC)                         │
│                                                                              │
│  Returns: Socket file descriptor (int) or -1 on error                       │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Address Structure

// IPv4 Address Structure
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));          // Zero out the structure
addr.sin_family = AF_INET;               // IPv4
addr.sin_port = htons(8080);             // Port (host to network byte order)
addr.sin_addr.s_addr = INADDR_ANY;       // Accept on any interface

// For specific IP address
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);

// IPv6 Address Structure
sockaddr_in6 addr6;
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(8080);
addr6.sin6_addr = in6addr_any;

Byte Order Functions

// Network byte order = Big Endian (most significant byte first)
// Host byte order = May be Big or Little Endian

htons(port);    // Host TO Network Short (16-bit, for ports)
htonl(addr);    // Host TO Network Long  (32-bit, for addresses)
ntohs(port);    // Network TO Host Short
ntohl(addr);    // Network TO Host Long
┌─────────────────────────────────────────────────────────────────────────────┐
│                           BYTE ORDER MATTERS!                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  Port 8080 (0x1F90) in different byte orders:                               │
│                                                                              │
│  Little Endian (x86):     Big Endian (Network):                             │
│  ┌─────┬─────┐            ┌─────┬─────┐                                     │
│  │ 90  │ 1F  │     ──►    │ 1F  │ 90  │                                     │
│  └─────┴─────┘   htons()  └─────┴─────┘                                     │
│                                                                              │
│  ALWAYS use htons() for ports and htonl() for addresses!                    │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

TCP Client

Connect to Server

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>

int connectToServer(const char* host, int port) {
    // Create socket
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) return -1;

    // Server address
    sockaddr_in serverAddr{};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    inet_pton(AF_INET, host, &serverAddr.sin_addr);

    // Connect
    if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        close(sock);
        return -1;
    }

    return sock;
}

void sendMessage(int sock, const string& msg) {
    send(sock, msg.c_str(), msg.length(), 0);
}

string receiveMessage(int sock) {
    char buffer[1024];
    ssize_t bytes = recv(sock, buffer, sizeof(buffer) - 1, 0);
    if (bytes > 0) {
        buffer[bytes] = '\0';
        return string(buffer);
    }
    return "";
}

TCP Server

Basic Server

int createServer(int port) {
    // Create socket
    int serverSock = socket(AF_INET, SOCK_STREAM, 0);

    // Allow reuse
    int opt = 1;
    setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // Bind
    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    bind(serverSock, (sockaddr*)&addr, sizeof(addr));

    // Listen
    listen(serverSock, 10);  // Backlog of 10

    return serverSock;
}

void acceptClients(int serverSock) {
    while (true) {
        sockaddr_in clientAddr;
        socklen_t clientLen = sizeof(clientAddr);

        // Accept (blocks)
        int clientSock = accept(serverSock,
                               (sockaddr*)&clientAddr,
                               &clientLen);

        if (clientSock >= 0) {
            // Handle client
            handleClient(clientSock);
            close(clientSock);
        }
    }
}

Multi-Threaded Server

void handleClient(int clientSock) {
    char buffer[1024];
    while (true) {
        ssize_t bytes = recv(clientSock, buffer, sizeof(buffer), 0);
        if (bytes <= 0) break;

        // Echo back
        send(clientSock, buffer, bytes, 0);
    }
}

void acceptClientsThreaded(int serverSock) {
    while (true) {
        sockaddr_in clientAddr;
        socklen_t clientLen = sizeof(clientAddr);
        int clientSock = accept(serverSock,
                               (sockaddr*)&clientAddr, &clientLen);

        if (clientSock >= 0) {
            thread t(handleClient, clientSock);
            t.detach();  // Run independently
        }
    }
}

UDP Communication

UDP Server

int createUDPServer(int port) {
    int sock = socket(AF_INET, SOCK_DGRAM, 0);

    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);

    bind(sock, (sockaddr*)&addr, sizeof(addr));
    return sock;
}

void receiveUDP(int sock) {
    char buffer[1024];
    sockaddr_in clientAddr;
    socklen_t clientLen = sizeof(clientAddr);

    ssize_t bytes = recvfrom(sock, buffer, sizeof(buffer), 0,
                             (sockaddr*)&clientAddr, &clientLen);

    if (bytes > 0) {
        buffer[bytes] = '\0';
        cout << "Received: " << buffer << endl;

        // Reply
        sendto(sock, "ACK", 3, 0,
               (sockaddr*)&clientAddr, clientLen);
    }
}

UDP Client

void sendUDP(const char* host, int port, const string& msg) {
    int sock = socket(AF_INET, SOCK_DGRAM, 0);

    sockaddr_in serverAddr{};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    inet_pton(AF_INET, host, &serverAddr.sin_addr);

    sendto(sock, msg.c_str(), msg.length(), 0,
           (sockaddr*)&serverAddr, sizeof(serverAddr));

    close(sock);
}

Non-Blocking I/O

select()

#include <sys/select.h>

void selectLoop(int serverSock, vector<int>& clients) {
    fd_set readSet;

    while (true) {
        FD_ZERO(&readSet);
        FD_SET(serverSock, &readSet);

        int maxFd = serverSock;
        for (int fd : clients) {
            FD_SET(fd, &readSet);
            maxFd = max(maxFd, fd);
        }

        timeval timeout = {1, 0};  // 1 second
        int ready = select(maxFd + 1, &readSet, nullptr, nullptr, &timeout);

        if (ready > 0) {
            // Check server socket
            if (FD_ISSET(serverSock, &readSet)) {
                int newClient = accept(serverSock, nullptr, nullptr);
                clients.push_back(newClient);
            }

            // Check client sockets
            for (int fd : clients) {
                if (FD_ISSET(fd, &readSet)) {
                    // Read from client
                }
            }
        }
    }
}

poll()

#include <poll.h>

void pollLoop(int serverSock) {
    vector<pollfd> fds;
    fds.push_back({serverSock, POLLIN, 0});

    while (true) {
        int ready = poll(fds.data(), fds.size(), 1000);  // 1s timeout

        if (ready > 0) {
            for (auto& pfd : fds) {
                if (pfd.revents & POLLIN) {
                    if (pfd.fd == serverSock) {
                        // Accept new connection
                    } else {
                        // Read from client
                    }
                }
            }
        }
    }
}

Best Practices

Learner Notes

The first design decision is usually TCP versus UDP. Choose TCP when correctness, ordering, and reliability matter more than latency. Choose UDP when the newest packet matters more than guaranteed delivery, such as games, streaming, or telemetry. After that, define the application protocol: how a message starts, how its length is known, how errors are represented, and how the connection closes.

Most beginner bugs come from assuming one recv() call equals one full message. TCP is a byte stream, not a message queue. You may receive half a message, one message, or several messages together. Real programs keep a buffer and parse complete frames from it.

Practice by writing a tiny echo protocol where each message starts with a 4-byte length followed by UTF-8 text. Then test what happens when the client sends two messages quickly or closes the connection mid-message.

✅ Do

// 1. Check return values
if (connect(sock, addr, len) < 0) {
    perror("connect failed");
}

// 2. Set SO_REUSEADDR
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

// 3. Close sockets properly
close(sock);

// 4. Handle partial reads/writes
ssize_t sendAll(int sock, const char* data, size_t len) {
    size_t sent = 0;
    while (sent < len) {
        ssize_t n = send(sock, data + sent, len - sent, 0);
        if (n <= 0) return -1;
        sent += n;
    }
    return sent;
}

❌ Don't

// 1. Don't ignore byte order
addr.sin_port = 8080;  // WRONG
addr.sin_port = htons(8080);  // Correct

// 2. Don't assume recv fills buffer
char buffer[1024];
recv(sock, buffer, 1024, 0);
buffer[1023] = '\0';  // May not be null-terminated!

// 3. Don't forget to close
// Memory/resource leak if socket not closed

Quick Reference

// Create socket
socket(AF_INET, SOCK_STREAM, 0);  // TCP
socket(AF_INET, SOCK_DGRAM, 0);   // UDP

// Address setup
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET, "ip", &addr.sin_addr);

// TCP Server
bind(sock, addr, sizeof(addr));
listen(sock, backlog);
accept(sock, clientAddr, &len);

// TCP Client
connect(sock, addr, sizeof(addr));

// Send/Receive
send(sock, data, len, 0);
recv(sock, buffer, buflen, 0);

// UDP
sendto(sock, data, len, 0, addr, addrlen);
recvfrom(sock, buf, len, 0, addr, &addrlen);

// Cleanup
close(sock);

Compile & Run

g++ -std=c++17 -Wall examples.cpp -o examples && ./examples

Skill Check

Test this lesson

Answer 4 quick questions to lock in the lesson and feed your adaptive practice queue.

--
Score
0/4
Answered
Not attempted
Status
1

Which module does this lesson belong to?

2

Which section is covered in this lesson content?

3

Which term is most central to this lesson?

4

What is the best way to use this lesson for real learning?

Your answers save locally first, then sync when account storage is available.
Practice queue