Expert Topics
Networking in C++
Table of Contents
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
}
}
}
}
}
}
Recommended Conventions
β 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
Cheat Sheet
// 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