🌐 Networking Concepts

C++ Implementation Examples

📊 Error Control Mechanisms

Error detection and correction algorithms for reliable data transmission

hamming.cpp

Implements Hamming code error detection and correction. Encodes 4-bit data into 7-bit Hamming code using parity bits at positions 1, 2, and 4. Can detect and correct single-bit errors in received data.

Compilation: g++ hamming.cpp -o hamming
Run: ./hamming
Usage: Enter 4 data bits when prompted, program generates Hamming code. Then enter received 7-bit code to check for errors and perform correction if needed.
Test Input:
1. Enter data bits: 1 0 1 1
2. Enter received code: 1 0 1 1 0 0 1 (introduces error at position 1)
Expected Output: Shows Hamming code generation, detects error at position 1, and corrects it.
#include <iostream>
#include <vector>
using namespace std;

void calculateParity(vector<int>& hamming) {
    hamming[0] = hamming[2] ^ hamming[4] ^ hamming[6];
    hamming[1] = hamming[2] ^ hamming[5] ^ hamming[6];
    hamming[3] = hamming[4] ^ hamming[5] ^ hamming[6];
}

int findError(vector<int>& hamming) {
    int p1 = hamming[0] ^ hamming[2] ^ hamming[4] ^ hamming[6];
    int p2 = hamming[1] ^ hamming[2] ^ hamming[5] ^ hamming[6];
    int p4 = hamming[3] ^ hamming[4] ^ hamming[5] ^ hamming[6];
    return p1 + 2*p2 + 4*p4;
}

int main() {
    vector<int> data(4);
    cout << "Enter 4 data bits: ";
    for(int i = 0; i < 4; i++) {
        cin >> data[i];
    }
    
    vector<int> hamming(7);
    hamming[2] = data[0];
    hamming[4] = data[1];
    hamming[5] = data[2];
    hamming[6] = data[3];
    
    calculateParity(hamming);
    
    cout << "Hamming code: ";
    for(int bit : hamming) {
        cout << bit << " ";
    }
    cout << endl;
    
    cout << "Enter received 7-bit code: ";
    for(int i = 0; i < 7; i++) {
        cin >> hamming[i];
    }
    
    int errorPos = findError(hamming);
    if(errorPos == 0) {
        cout << "No error detected" << endl;
    } else {
        cout << "Error at position: " << errorPos << endl;
        hamming[errorPos-1] ^= 1;
        cout << "Corrected code: ";
        for(int bit : hamming) {
            cout << bit << " ";
        }
        cout << endl;
    }
    
    return 0;
}

crc.cpp

Implements Cyclic Redundancy Check (CRC) for error detection. Performs modulo-2 division using XOR operations to generate CRC codeword and detect errors in received data.

Compilation: g++ crc.cpp -o crc
Run: ./crc
Usage: Enter data bits and generator polynomial when prompted. Program generates CRC codeword. Then enter received codeword to check for transmission errors.
Test Input:
1. Enter data bits: 1010
2. Enter generator: 1101
3. Enter received codeword: 1010110 (introduces error)
Expected Output: Generates CRC codeword 1010001, then detects error in received data.
#include <iostream>
#include <string>
using namespace std;

string xorOperation(string a, string b) {
    string result = "";
    for(int i = 1; i < b.length(); i++) {
        if(a[i] == b[i]) {
            result += "0";
        } else {
            result += "1";
        }
    }
    return result;
}

string modulo2Division(string dividend, string divisor) {
    int pick = divisor.length();
    string tmp = dividend.substr(0, pick);
    
    while(pick < dividend.length()) {
        if(tmp[0] == '1') {
            tmp = xorOperation(divisor, tmp) + dividend[pick];
        } else {
            tmp = xorOperation(string(divisor.length(), '0'), tmp) + dividend[pick];
        }
        pick++;
    }
    
    if(tmp[0] == '1') {
        tmp = xorOperation(divisor, tmp);
    } else {
        tmp = xorOperation(string(divisor.length(), '0'), tmp);
    }
    
    return tmp;
}

int main() {
    string data, generator;
    cout << "Enter data bits: ";
    cin >> data;
    cout << "Enter generator polynomial: ";
    cin >> generator;
    
    string codeword = data + string(generator.length() - 1, '0');
    string remainder = modulo2Division(codeword, generator);
    
    codeword = data + remainder;
    cout << "CRC codeword: " << codeword << endl;
    
    cout << "Enter received codeword: ";
    cin >> codeword;
    
    remainder = modulo2Division(codeword, generator);
    
    bool hasError = false;
    for(char bit : remainder) {
        if(bit == '1') {
            hasError = true;
            break;
        }
    }
    
    if(hasError) {
        cout << "Error detected!" << endl;
    } else {
        cout << "No error detected" << endl;
    }
    
    return 0;
}

🔌 Socket Programming

Network programming examples using TCP and UDP protocols

tcp_server.cpp

TCP echo server that listens on port 8080, accepts client connections, and echoes back received messages. Uses reliable TCP connection for communication.

Compilation: g++ tcp_server.cpp -o tcp_server
Run: ./tcp_server
Usage: Run the server first, then connect with TCP client. Server will echo back any messages received from clients.
Test Steps:
1. Terminal 1: ./tcp_server
2. Terminal 2: ./tcp_client
3. Type messages in client, see echo from server
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
using namespace std;

int main() {
    int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8080);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    
    bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    listen(serverSocket, 5);
    
    cout << "TCP Server listening on port 8080..." << endl;
    
    int clientSocket = accept(serverSocket, NULL, NULL);
    char buffer[1024];
    
    while(true) {
        memset(buffer, 0, sizeof(buffer));
        int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);
        
        if(bytesRead <= 0) break;
        
        cout << "Received: " << buffer << endl;
        send(clientSocket, buffer, strlen(buffer), 0);
    }
    
    close(clientSocket);
    close(serverSocket);
    return 0;
}

tcp_client.cpp

TCP client that connects to server on localhost:8080, sends messages and receives echoed responses. Provides interactive interface for message exchange.

Compilation: g++ tcp_client.cpp -o tcp_client
Run: ./tcp_client
Usage: Ensure TCP server is running first. Enter messages when prompted. Type 'quit' to exit the client.
Test Input:
1. Hello Server
2. This is a test message
3. quit (to exit)
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
using namespace std;

int main() {
    int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
    
    connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    
    char buffer[1024];
    string message;
    
    while(true) {
        cout << "Enter message (quit to exit): ";
        getline(cin, message);
        
        if(message == "quit") break;
        
        send(clientSocket, message.c_str(), message.length(), 0);
        
        memset(buffer, 0, sizeof(buffer));
        recv(clientSocket, buffer, sizeof(buffer), 0);
        cout << "Echo: " << buffer << endl;
    }
    
    close(clientSocket);
    return 0;
}

udp_server.cpp

UDP echo server that listens on port 8080 and echoes back messages from any UDP client. Uses connectionless UDP protocol for communication.

Compilation: g++ udp_server.cpp -o udp_server
Run: ./udp_server
Usage: Run the server first, then connect with UDP clients. Server will echo back messages to the sender's address.
Test Steps:
1. Terminal 1: ./udp_server
2. Terminal 2: ./udp_client
3. Send messages from client to test UDP communication
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
using namespace std;

int main() {
    int serverSocket = socket(AF_INET, SOCK_DGRAM, 0);
    
    struct sockaddr_in serverAddr, clientAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8080);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    
    bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    cout << "UDP Server listening on port 8080..." << endl;
    
    char buffer[1024];
    socklen_t clientLen = sizeof(clientAddr);
    
    while(true) {
        memset(buffer, 0, sizeof(buffer));
        recvfrom(serverSocket, buffer, sizeof(buffer), 0, 
                (struct sockaddr*)&clientAddr, &clientLen);
        
        cout << "Received: " << buffer << endl;
        sendto(serverSocket, buffer, strlen(buffer), 0, 
               (struct sockaddr*)&clientAddr, clientLen);
    }
    
    close(serverSocket);
    return 0;
}

udp_client.cpp

UDP client that sends messages to server on localhost:8080 and receives echoed responses. Uses connectionless UDP protocol with interactive interface.

Compilation: g++ udp_client.cpp -o udp_client
Run: ./udp_client
Usage: Ensure UDP server is running first. Enter messages when prompted. Type 'quit' to exit the client.
Test Input:
1. Hello UDP Server
2. UDP Message Test
3. quit (to exit)
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
using namespace std;

int main() {
    int clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
    
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
    
    char buffer[1024];
    string message;
    socklen_t serverLen = sizeof(serverAddr);
    
    while(true) {
        cout << "Enter message (quit to exit): ";
        getline(cin, message);
        
        if(message == "quit") break;
        
        sendto(clientSocket, message.c_str(), message.length(), 0,
               (struct sockaddr*)&serverAddr, serverLen);
        
        memset(buffer, 0, sizeof(buffer));
        recvfrom(clientSocket, buffer, sizeof(buffer), 0, NULL, NULL);
        cout << "Echo: " << buffer << endl;
    }
    
    close(clientSocket);
    return 0;
}

chat_server.cpp

Multi-client TCP chat server using select() for handling multiple clients simultaneously. Broadcasts messages from one client to all other connected clients.

Compilation: g++ chat_server.cpp -o chat_server
Run: ./chat_server
Usage: Run the server, then connect multiple TCP clients (like telnet localhost 8080). Messages from one client are broadcasted to all other clients.
Test Steps:
1. Terminal 1: ./chat_server
2. Terminal 2: telnet localhost 8080
3. Terminal 3: telnet localhost 8080
4. Type messages in one terminal, see broadcast in others
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
using namespace std;

int main() {
    int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    int clients[10] = {0};
    int maxClients = 10;
    
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8080);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    
    bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    listen(serverSocket, 5);
    
    cout << "Chat Server listening on port 8080..." << endl;
    
    fd_set readfds;
    char buffer[1024];
    
    while(true) {
        FD_ZERO(&readfds);
        FD_SET(serverSocket, &readfds);
        int maxfd = serverSocket;
        
        for(int i = 0; i < maxClients; i++) {
            if(clients[i] > 0) {
                FD_SET(clients[i], &readfds);
                if(clients[i] > maxfd) maxfd = clients[i];
            }
        }
        
        select(maxfd + 1, &readfds, NULL, NULL, NULL);
        
        if(FD_ISSET(serverSocket, &readfds)) {
            int newClient = accept(serverSocket, NULL, NULL);
            for(int i = 0; i < maxClients; i++) {
                if(clients[i] == 0) {
                    clients[i] = newClient;
                    cout << "New client connected: " << newClient << endl;
                    break;
                }
            }
        }
        
        for(int i = 0; i < maxClients; i++) {
            if(clients[i] > 0 && FD_ISSET(clients[i], &readfds)) {
                memset(buffer, 0, sizeof(buffer));
                int bytesRead = recv(clients[i], buffer, sizeof(buffer), 0);
                
                if(bytesRead <= 0) {
                    close(clients[i]);
                    clients[i] = 0;
                } else {
                    for(int j = 0; j < maxClients; j++) {
                        if(clients[j] > 0 && clients[j] != clients[i]) {
                            send(clients[j], buffer, strlen(buffer), 0);
                        }
                    }
                }
            }
        }
    }
    
    return 0;
}

🌐 IP Addressing

IP address analysis and subnet calculations

classful.cpp

Analyzes IP addresses and determines their class (A, B, C, D, E) based on the first octet. Displays network address, default subnet mask, and host range for each class.

Compilation: g++ classful.cpp -o classful
Run: ./classful
Usage: Enter an IP address in dotted decimal notation (e.g., 192.168.1.100). Program will identify the class and display relevant network information.
Test Inputs:
1. Class A: 10.0.0.1
2. Class B: 172.16.0.1
3. Class C: 192.168.1.100
4. Class D: 224.0.0.1
#include <iostream>
#include <string>
using namespace std;

void parseIP(string ip, int& a, int& b, int& c, int& d) {
    sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d);
}

int main() {
    string ip;
    cout << "Enter IP address: ";
    cin >> ip;
    
    int a, b, c, d;
    parseIP(ip, a, b, c, d);
    
    if(a >= 1 && a <= 126) {
        cout << "Class A" << endl;
        cout << "Network: " << a << ".0.0.0" << endl;
        cout << "Default mask: 255.0.0.0" << endl;
        cout << "Host range: " << a << ".0.0.1 to " << a << ".255.255.254" << endl;
    }
    else if(a >= 128 && a <= 191) {
        cout << "Class B" << endl;
        cout << "Network: " << a << "." << b << ".0.0" << endl;
        cout << "Default mask: 255.255.0.0" << endl;
        cout << "Host range: " << a << "." << b << ".0.1 to " << a << "." << b << ".255.254" << endl;
    }
    else if(a >= 192 && a <= 223) {
        cout << "Class C" << endl;
        cout << "Network: " << a << "." << b << "." << c << ".0" << endl;
        cout << "Default mask: 255.255.255.0" << endl;
        cout << "Host range: " << a << "." << b << "." << c << ".1 to " << a << "." << b << "." << c << ".254" << endl;
    }
    else if(a >= 224 && a <= 239) {
        cout << "Class D (Multicast)" << endl;
    }
    else {
        cout << "Class E (Reserved)" << endl;
    }
    
    return 0;
}

cidr.cpp

Processes CIDR notation addresses and calculates network information including network address, subnet mask, broadcast address, host range, and total available hosts.

Compilation: g++ cidr.cpp -o cidr
Run: ./cidr
Usage: Enter network address in CIDR notation (e.g., 192.168.1.0/24). Program will calculate and display all network parameters.
Test Inputs:
1. 192.168.1.0/24 (Class C with /24)
2. 10.0.0.0/8 (Class A with /8)
3. 172.16.0.0/16 (Class B with /16)
4. 192.168.0.0/25 (Subnet with /25)
#include <iostream>
#include <string>
#include <cmath>
using namespace std;

void parseIP(string ip, int& a, int& b, int& c, int& d) {
    sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d);
}

unsigned int ipToInt(int a, int b, int c, int d) {
    return (a << 24) | (b << 16) | (c << 8) | d;
}

void intToIP(unsigned int ip, int& a, int& b, int& c, int& d) {
    a = (ip >> 24) & 0xFF;
    b = (ip >> 16) & 0xFF;
    c = (ip >> 8) & 0xFF;
    d = ip & 0xFF;
}

int main() {
    string cidr;
    cout << "Enter CIDR notation (e.g., 192.168.1.0/24): ";
    cin >> cidr;
    
    size_t pos = cidr.find('/');
    string ip = cidr.substr(0, pos);
    int prefix = stoi(cidr.substr(pos + 1));
    
    int a, b, c, d;
    parseIP(ip, a, b, c, d);
    
    unsigned int mask = 0xFFFFFFFF << (32 - prefix);
    unsigned int ipAddr = ipToInt(a, b, c, d);
    unsigned int network = ipAddr & mask;
    unsigned int broadcast = network | (~mask);
    
    int hostBits = 32 - prefix;
    int totalHosts = pow(2, hostBits) - 2;
    
    int na, nb, nc, nd, ba, bb, bc, bd, ma, mb, mc, md;
    intToIP(network, na, nb, nc, nd);
    intToIP(broadcast, ba, bb, bc, bd);
    intToIP(mask, ma, mb, mc, md);
    
    cout << "Network: " << na << "." << nb << "." << nc << "." << nd << endl;
    cout << "Subnet mask: " << ma << "." << mb << "." << mc << "." << md << endl;
    cout << "Broadcast: " << ba << "." << bb << "." << bc << "." << bd << endl;
    cout << "Host range: " << na << "." << nb << "." << nc << "." << (nd+1) 
         << " to " << ba << "." << bb << "." << bc << "." << (bd-1) << endl;
    cout << "Total hosts: " << totalHosts << endl;
    
    return 0;
}

subnetting.cpp

Performs subnet calculation by dividing a network into smaller subnets. Calculates new prefix length and displays network details for each subnet including addresses and host ranges.

Compilation: g++ subnetting.cpp -o subnetting
Run: ./subnetting
Usage: Enter network address, original prefix length, and number of required subnets. Program will calculate optimal subnetting and display all subnet information.
Test Inputs:
1. Network: 192.168.0.0
2. Original prefix: 24
3. Number of subnets: 4
Expected Output: Creates 4 subnets with /26 prefix, each with 62 hosts.
#include <iostream>
#include <string>
#include <cmath>
using namespace std;

void parseIP(string ip, int& a, int& b, int& c, int& d) {
    sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d);
}

unsigned int ipToInt(int a, int b, int c, int d) {
    return (a << 24) | (b << 16) | (c << 8) | d;
}

void intToIP(unsigned int ip, int& a, int& b, int& c, int& d) {
    a = (ip >> 24) & 0xFF;
    b = (ip >> 16) & 0xFF;
    c = (ip >> 8) & 0xFF;
    d = ip & 0xFF;
}

int main() {
    string ip;
    int originalPrefix, subnets;
    
    cout << "Enter network (e.g., 192.168.1.0): ";
    cin >> ip;
    cout << "Enter original prefix length: ";
    cin >> originalPrefix;
    cout << "Enter number of subnets needed: ";
    cin >> subnets;
    
    int subnetBits = ceil(log2(subnets));
    int newPrefix = originalPrefix + subnetBits;
    
    if(newPrefix > 30) {
        cout << "Too many subnets for this network!" << endl;
        return 1;
    }
    
    int a, b, c, d;
    parseIP(ip, a, b, c, d);
    unsigned int baseNetwork = ipToInt(a, b, c, d);
    
    unsigned int subnetSize = 1 << (32 - newPrefix);
    
    cout << "\nSubnet Information:" << endl;
    cout << "New prefix length: /" << newPrefix << endl;
    cout << "Hosts per subnet: " << (subnetSize - 2) << endl;
    
    for(int i = 0; i < subnets; i++) {
        unsigned int subnetAddr = baseNetwork + (i * subnetSize);
        unsigned int broadcastAddr = subnetAddr + subnetSize - 1;
        
        int sa, sb, sc, sd, ba, bb, bc, bd;
        intToIP(subnetAddr, sa, sb, sc, sd);
        intToIP(broadcastAddr, ba, bb, bc, bd);
        
        cout << "\nSubnet " << (i+1) << ":" << endl;
        cout << "Network: " << sa << "." << sb << "." << sc << "." << sd << "/" << newPrefix << endl;
        cout << "Broadcast: " << ba << "." << bb << "." << bc << "." << bd << endl;
        cout << "Host range: " << sa << "." << sb << "." << sc << "." << (sd+1) 
             << " to " << ba << "." << bb << "." << bc << "." << (bd-1) << endl;
    }
    
    return 0;
}
Code copied to clipboard!