cpp

examples

examples.cpp⚙️
/**
 * Networking - Examples
 * Compile: g++ -std=c++17 -Wall examples.cpp -o examples
 * 
 * Note: Run server and client in separate terminals
 */

#include <iostream>
#include <string>
#include <cstring>
#include <thread>
#include <vector>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;

const int PORT = 8888;
const int BUFFER_SIZE = 1024;

// ============================================================
// SECTION 1: TCP CLIENT
// ============================================================

class TCPClient {
    int sock;
    bool connected = false;
    
public:
    TCPClient() : sock(-1) {}
    
    bool connectTo(const string& host, int port) {
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            cerr << "Failed to create socket" << endl;
            return false;
        }
        
        sockaddr_in serverAddr{};
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(port);
        
        if (inet_pton(AF_INET, host.c_str(), &serverAddr.sin_addr) <= 0) {
            cerr << "Invalid address" << endl;
            return false;
        }
        
        if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
            cerr << "Connection failed" << endl;
            return false;
        }
        
        connected = true;
        cout << "  Connected to " << host << ":" << port << endl;
        return true;
    }
    
    bool sendData(const string& data) {
        if (!connected) return false;
        ssize_t sent = send(sock, data.c_str(), data.length(), 0);
        return sent == (ssize_t)data.length();
    }
    
    string receive() {
        if (!connected) return "";
        char buffer[BUFFER_SIZE];
        ssize_t bytes = recv(sock, buffer, BUFFER_SIZE - 1, 0);
        if (bytes > 0) {
            buffer[bytes] = '\0';
            return string(buffer);
        }
        return "";
    }
    
    void disconnect() {
        if (sock >= 0) {
            close(sock);
            sock = -1;
            connected = false;
        }
    }
    
    ~TCPClient() { disconnect(); }
};

// ============================================================
// SECTION 2: TCP SERVER
// ============================================================

class TCPServer {
    int serverSock;
    bool running = false;
    
public:
    TCPServer() : serverSock(-1) {}
    
    bool start(int port) {
        serverSock = socket(AF_INET, SOCK_STREAM, 0);
        if (serverSock < 0) {
            cerr << "Failed to create socket" << endl;
            return false;
        }
        
        // Allow address reuse
        int opt = 1;
        setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        
        sockaddr_in addr{};
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(port);
        
        if (bind(serverSock, (sockaddr*)&addr, sizeof(addr)) < 0) {
            cerr << "Bind failed" << endl;
            return false;
        }
        
        if (listen(serverSock, 5) < 0) {
            cerr << "Listen failed" << endl;
            return false;
        }
        
        running = true;
        cout << "  Server listening on port " << port << endl;
        return true;
    }
    
    void handleClient(int clientSock) {
        char buffer[BUFFER_SIZE];
        
        while (true) {
            ssize_t bytes = recv(clientSock, buffer, BUFFER_SIZE - 1, 0);
            if (bytes <= 0) break;
            
            buffer[bytes] = '\0';
            cout << "  Received: " << buffer << endl;
            
            // Echo back
            string response = "Echo: " + string(buffer);
            send(clientSock, response.c_str(), response.length(), 0);
        }
        
        close(clientSock);
        cout << "  Client disconnected" << endl;
    }
    
    void acceptOne() {
        sockaddr_in clientAddr;
        socklen_t clientLen = sizeof(clientAddr);
        
        int clientSock = accept(serverSock, (sockaddr*)&clientAddr, &clientLen);
        if (clientSock >= 0) {
            char clientIP[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, INET_ADDRSTRLEN);
            cout << "  Client connected from " << clientIP << endl;
            
            handleClient(clientSock);
        }
    }
    
    void stop() {
        if (serverSock >= 0) {
            close(serverSock);
            serverSock = -1;
            running = false;
        }
    }
    
    ~TCPServer() { stop(); }
};

// ============================================================
// SECTION 3: UDP EXAMPLE
// ============================================================

class UDPSocket {
    int sock;
    
public:
    UDPSocket() {
        sock = socket(AF_INET, SOCK_DGRAM, 0);
    }
    
    bool bindTo(int port) {
        sockaddr_in addr{};
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(port);
        return bind(sock, (sockaddr*)&addr, sizeof(addr)) >= 0;
    }
    
    bool sendTo(const string& host, int port, const string& data) {
        sockaddr_in addr{};
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        inet_pton(AF_INET, host.c_str(), &addr.sin_addr);
        
        return sendto(sock, data.c_str(), data.length(), 0,
                     (sockaddr*)&addr, sizeof(addr)) >= 0;
    }
    
    string receiveFrom(string& senderIP, int& senderPort) {
        char buffer[BUFFER_SIZE];
        sockaddr_in senderAddr;
        socklen_t senderLen = sizeof(senderAddr);
        
        ssize_t bytes = recvfrom(sock, buffer, BUFFER_SIZE - 1, 0,
                                (sockaddr*)&senderAddr, &senderLen);
        
        if (bytes > 0) {
            buffer[bytes] = '\0';
            char ip[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &senderAddr.sin_addr, ip, INET_ADDRSTRLEN);
            senderIP = ip;
            senderPort = ntohs(senderAddr.sin_port);
            return string(buffer);
        }
        return "";
    }
    
    ~UDPSocket() { close(sock); }
};

// ============================================================
// DEMO FUNCTIONS
// ============================================================

void demoTCPEcho() {
    cout << "--- TCP Echo Demo ---" << endl;
    cout << "  (Server and client in same process for demo)" << endl;
    
    // This would normally be separate processes
    // Just showing the API usage
    
    TCPServer server;
    if (!server.start(PORT)) {
        cout << "  Server failed to start" << endl;
        return;
    }
    
    // In real usage, client would be in separate process
    cout << "  Server started on port " << PORT << endl;
    cout << "  (Demo complete - run server/client separately for real test)" << endl;
    
    server.stop();
}

void demoSocketInfo() {
    cout << "\n--- Socket Information ---" << endl;
    
    // Address conversion
    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    inet_pton(AF_INET, "192.168.1.1", &addr.sin_addr);
    
    // Convert back to string
    char ipStr[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &addr.sin_addr, ipStr, INET_ADDRSTRLEN);
    cout << "  IP: " << ipStr << endl;
    cout << "  Port: " << ntohs(addr.sin_port) << endl;
    
    // Byte order
    cout << "\n  Byte order functions:" << endl;
    cout << "  htons(1234) = " << htons(1234) << endl;
    cout << "  htonl(12345678) = " << htonl(12345678) << endl;
}

void demoUDP() {
    cout << "\n--- UDP Demo ---" << endl;
    
    UDPSocket sock;
    cout << "  UDP socket created" << endl;
    cout << "  (Bind/send/receive work similarly to TCP)" << endl;
}

// ============================================================
// SIMPLE ECHO SERVER (Standalone)
// ============================================================

void runEchoServer() {
    cout << "\n--- Running Echo Server ---" << endl;
    
    int serverSock = socket(AF_INET, SOCK_STREAM, 0);
    
    int opt = 1;
    setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    
    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(serverSock, 5);
    
    cout << "  Echo server on port " << PORT << endl;
    cout << "  (Press Ctrl+C to stop)" << endl;
    cout << "  Test with: nc localhost " << PORT << endl;
    
    while (true) {
        sockaddr_in clientAddr;
        socklen_t clientLen = sizeof(clientAddr);
        int clientSock = accept(serverSock, (sockaddr*)&clientAddr, &clientLen);
        
        if (clientSock >= 0) {
            cout << "  Client connected" << endl;
            
            char buffer[BUFFER_SIZE];
            ssize_t bytes;
            while ((bytes = recv(clientSock, buffer, BUFFER_SIZE, 0)) > 0) {
                send(clientSock, buffer, bytes, 0);
            }
            
            close(clientSock);
            cout << "  Client disconnected" << endl;
        }
    }
    
    close(serverSock);
}

// ============================================================
// MAIN
// ============================================================

int main(int argc, char* argv[]) {
    cout << "╔══════════════════════════════════════╗" << endl;
    cout << "║      NETWORKING - EXAMPLES           ║" << endl;
    cout << "╚══════════════════════════════════════╝" << endl;
    
    if (argc > 1 && string(argv[1]) == "server") {
        runEchoServer();
        return 0;
    }
    
    demoSocketInfo();
    demoTCPEcho();
    demoUDP();
    
    cout << "\n--- How to Test ---" << endl;
    cout << "  1. Run: ./examples server" << endl;
    cout << "  2. In another terminal: nc localhost " << PORT << endl;
    cout << "  3. Type messages - they'll be echoed back" << endl;
    
    cout << "\n=== Complete ===" << endl;
    return 0;
}
Examples - C++ Tutorial | DeepML