Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

Socket-Programmierung in C++: Einfacher TCP-Client und -Server unter Linux (COP4600 Ex9)

Lerne Schritt für Schritt, wie du mit Sockets in C++ einen TCP-Client und -Server erstellst. Basierend auf der COP4600 Ex9: Networking 2 – inklusive Beispielcode und Erklärungen.

Socket-Programmierung C++ TCP-Client Server C++ COP4600 Ex9 Lösung Linux Socket Programmierung C++ Netzwerkprogrammierung Berkeley Sockets C++ Client Server Kommunikation C++ Socket Tutorial Deutsch Programmieren lernen C++ Netzwerk Reptilian Socket Aufgabe TCP/IP Socket Beispiel C++ Socket bind listen accept Einfacher Chat mit Sockets Socket Programmierung Studium COP4600 Networking 2 C++ Socket connect send recv

Einführung in die Socket-Programmierung mit C++

Die Socket-Programmierung ist ein zentrales Thema in der Netzwerkkommunikation. In diesem Tutorial lernst du, wie du mit C++ unter Linux einen einfachen TCP-Client und -Server erstellst, die Nachrichten austauschen. Dies entspricht der Aufgabenstellung COP4600 Ex9: Networking 2. Wir verwenden dabei die Berkeley Sockets API, die unter Linux und anderen Unix-ähnlichen Systemen Standard ist.

Was sind Sockets?

Ein Socket ist ein Endpunkt für die Kommunikation zwischen zwei Programmen über ein Netzwerk. Ein TCP-Socket ist an eine IP-Adresse und einen Port gebunden. Stell dir vor, du spielst ein Online-Spiel wie Fortnite: Dein Client (dein PC) verbindet sich über einen Socket mit dem Spielserver, der auf einem bestimmten Port lauscht. Die Socket-Programmierung ist die Grundlage für jede Netzwerkanwendung – von Chatprogrammen bis zu Cloud-Diensten.

Grundlegende Schritte der Socket-Programmierung

  • Server: Socket erstellen, an IP/Port binden, auf Verbindungen warten (listen), Verbindung akzeptieren (accept), Daten senden/empfangen.
  • Client: Socket erstellen, mit Server verbinden (connect), Daten senden/empfangen.

Voraussetzungen

Du benötigst einen Linux-Rechner (z.B. die Reptilian-Maschine aus der Aufgabe) und einen C++-Compiler (g++). Stelle sicher, dass die Netzwerkschnittstelle (loopback) funktioniert.

Server-Code (server.cpp)

Der Server erstellt einen Socket, bindet ihn an eine IP (z.B. 127.0.0.1) und einen Port, lauscht auf eingehende Verbindungen und akzeptiert eine Verbindung. Danach sendet er eine Begrüßung und empfängt eine Nachricht vom Client.

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

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <port>\n";
        return 1;
    }
    int port = std::stoi(argv[1]);
    
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        std::cerr << "Socket creation failed\n";
        return 1;
    }
    
    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);
    
    if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
        std::cerr << "Bind failed\n";
        return 1;
    }
    
    if (listen(server_fd, 1) < 0) {
        std::cerr << "Listen failed\n";
        return 1;
    }
    
    std::cout << "Server listening on port " << port << "\n";
    
    int addrlen = sizeof(address);
    int new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
    if (new_socket < 0) {
        std::cerr << "Accept failed\n";
        return 1;
    }
    
    // Nachricht vom Client empfangen
    char buffer[1024] = {0};
    read(new_socket, buffer, 1024);
    std::cout << "Client: " << buffer << std::endl;
    
    // Nachricht an Client senden
    const char* msg = "Welcome to the server running on REPTILIAN";
    send(new_socket, msg, strlen(msg), 0);
    
    close(new_socket);
    close(server_fd);
    return 0;
}

Client-Code (client.cpp)

Der Client verbindet sich mit dem Server und sendet eine Nachricht, bevor er die Antwort empfängt.

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

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <port>\n";
        return 1;
    }
    int port = std::stoi(argv[1]);
    
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        std::cerr << "Socket creation failed\n";
        return 1;
    }
    
    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
        std::cerr << "Invalid address\n";
        return 1;
    }
    
    if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        std::cerr << "Connection failed\n";
        return 1;
    }
    
    // Nachricht an Server senden
    const char* msg = "Hallo Server, ich bin der Client!";
    send(sock, msg, strlen(msg), 0);
    
    // Antwort empfangen
    char buffer[1024] = {0};
    read(sock, buffer, 1024);
    std::cout << "Server: " << buffer << std::endl;
    
    close(sock);
    return 0;
}

Ausführung und erwartete Ausgabe

Kompiliere beide Programme mit g++ server.cpp -o server und g++ client.cpp -o client. Starte zuerst den Server: ./server 1234. Öffne ein zweites Terminal und starte den Client: ./client 1234. Der Server sollte die Nachricht des Clients ausgeben, und der Client die Begrüßung des Servers.

Hinweis: Falls Probleme mit localhost auftreten, überprüfe die Netzwerkkonfiguration oder verwende 127.0.0.1 explizit.

Häufige Fehler und Lösungen

  • Bind fehlgeschlagen: Port bereits belegt. Verwende einen anderen Port oder warte, bis der vorherige Prozess beendet ist.
  • Verbindung verweigert: Server läuft nicht oder falscher Port. Stelle sicher, dass Server und Client denselben Port verwenden.
  • Keine Daten empfangen: Überprüfe, ob send/read korrekt aufgerufen werden. Vergiss nicht, den Puffer zu leeren.

Trendbeispiel: Chat zwischen KI-Assistenten

Stell dir vor, zwei KI-Assistenten wie ChatGPT und ein lokaler Bot tauschen über Sockets Nachrichten aus. Der Server könnte ein zentraler Bot sein, der Anfragen von mehreren Clients entgegennimmt. Dieses Grundprinzip wird in vielen modernen Anwendungen genutzt, von Microservices bis zu IoT-Geräten.

Zusammenfassung

Du hast erfolgreich einen einfachen TCP-Client und -Server in C++ implementiert. Dieses Wissen ist die Basis für komplexere Netzwerkanwendungen. Für die Abgabe der COP4600 Ex9 denk daran, Screenshots und die Quellcodedateien bereitzustellen.