cpp
Networking
02_Networking⚙️cpp
// Module 10: Expert Topics
// Lesson: Systems Networking Essentials
// Build (Linux/macOS): g++ -std=c++17 01_networking.cpp -o networking_demo
// Note: The demo uses POSIX sockets. On Windows, compile with Winsock adjustments or use ASIO.
#include <chrono>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <string>
#include <thread>
#if defined(_WIN32)
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
using namespace std;
constexpr uint16_t kPort = 45'123;
constexpr const char *kMessage = "Hello over TCP";
void printPart(const string &title)
{
cout << "\n========== " << title << " ==========" << endl;
}
#ifndef _WIN32
// PART 1: Minimal TCP echo server that handles a single client.
void runServer()
{
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0)
{
perror("socket");
return;
}
int opt = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(kPort);
if (bind(server_fd, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) < 0)
{
perror("bind");
close(server_fd);
return;
}
if (listen(server_fd, 1) < 0)
{
perror("listen");
close(server_fd);
return;
}
cout << "Server listening on 127.0.0.1:" << kPort << endl;
sockaddr_in client_addr{};
socklen_t len = sizeof(client_addr);
int client_fd = accept(server_fd, reinterpret_cast<sockaddr *>(&client_addr), &len);
if (client_fd < 0)
{
perror("accept");
close(server_fd);
return;
}
char buffer[256] = {};
ssize_t received = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
if (received > 0)
{
cout << "Server received: " << buffer << endl;
string reply = string("Echo: ") + buffer;
send(client_fd, reply.c_str(), reply.size(), 0);
}
close(client_fd);
close(server_fd);
}
// PART 2: Simple client that talks to the server.
void runClient()
{
this_thread::sleep_for(chrono::milliseconds(200)); // give server time to listen
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror("socket");
return;
}
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(kPort);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
if (connect(sock, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) < 0)
{
perror("connect");
close(sock);
return;
}
send(sock, kMessage, strlen(kMessage), 0);
char buffer[256] = {};
ssize_t received = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (received > 0)
{
cout << "Client received: " << buffer << endl;
}
close(sock);
}
#endif
// PART 3: Protocol design considerations.
void discussProtocols()
{
printPart("PART 3: Designing Network Protocols");
cout << "- Choose TCP for reliable ordered delivery; UDP for low-latency datagrams." << endl;
cout << "- Define clear message boundaries (length-prefix, delimiter, or fixed-size)." << endl;
cout << "- Consider serialization formats: JSON, Protocol Buffers, FlatBuffers." << endl;
cout << "- Always validate input from the network and authenticate peers when needed." << endl;
}
// PART 4: High-level networking stacks.
void discussHighLevelAPIs()
{
printPart("PART 4: High-Level Networking Options");
cout << "asio (Boost or standalone) provides portable async I/O." << endl;
cout << "gRPC builds on HTTP/2 with strong tooling for RPC services." << endl;
cout << "REST over HTTP can be served with cpp-httplib, drogon, oatpp, or served via NGINX." << endl;
cout << "WebSocket libraries enable realtime messaging (uWebSockets, beast)." << endl;
}
int main()
{
printPart("PARTS 1 & 2: Loopback Echo Demo");
#if defined(_WIN32)
cout << "This minimal demo requires POSIX sockets. Use Winsock or ASIO on Windows." << endl;
#else
thread server(runServer);
thread client(runClient);
server.join();
client.join();
#endif
discussProtocols();
discussHighLevelAPIs();
cout << "\nExercises:\n"
<< "1. Extend the server to handle multiple clients concurrently using std::thread.\n"
<< "2. Implement a UDP ping/pong pair and measure round-trip time.\n"
<< "3. Prototype a JSON-based protocol with message framing.\n"
<< "4. Explore header-only ASIO to avoid platform-specific socket code.\n";
return 0;
}