Skip to content
IRC-Coding IRC-Coding
Netzwerkprotokolle TCP UDP IP DNS HTTP HTTPS OSI Modell TCP IP Stack

Netzwerkprotokolle: TCP, UDP, IP, DNS, HTTP/HTTPS & OSI/TCP-IP-Modelle

Netzwerkprotokolle Grundlagen mit TCP, UDP, IP, DNS, HTTP/HTTPS. OSI-Modell und TCP/IP-Stack mit praktischen Beispielen für Netzwerkkommunikation.

S

schutzgeist

2 min read

Netzwerkprotokolle: TCP, UDP, IP, DNS, HTTP/HTTPS & OSI/TCP-IP-Modelle

Dieser Beitrag ist eine umfassende Einführung in die Netzwerkprotokolle – inklusive TCP, UDP, IP, DNS, HTTP/HTTPS, OSI-Modell und TCP/IP-Stack mit praktischen Beispielen.

In a Nutshell

Netzwerkprotokolle regeln die Kommunikation zwischen Computern. TCP/IP ist das grundlegende Protokoll-Stack, OSI beschreibt 7 Schichten, HTTP/HTTPS ermöglichen Web-Kommunikation und DNS löst Namen in IPs auf.

Kompakte Fachbeschreibung

Netzwerkprotokolle sind standardisierte Regeln und Konventionen für die Datenkommunikation zwischen Computern in einem Netzwerk.

Wichtige Protokolle:

TCP (Transmission Control Protocol)

  • Typ: Verbindungsorientiert, zuverlässig
  • Features: 3-Wege-Handshake, Flusskontrolle, Fehlerkorrektur
  • Anwendung: Web, E-Mail, Dateitransfer
  • Port: 80 (HTTP), 443 (HTTPS), 25 (SMTP)

UDP (User Datagram Protocol)

  • Typ: Verbindungslos, unzuverlässig
  • Features: Einfach, schnell, keine Garantien
  • Anwendung: Streaming, Gaming, DNS
  • Port: 53 (DNS), 123 (NTP), 67 (DHCP)

IP (Internet Protocol)

  • Typ: Paketvermittlung, Routing
  • Versionen: IPv4 (32 Bit), IPv6 (128 Bit)
  • Features: Adressierung, Fragmentierung
  • Anwendung: Grundlage für Internet

DNS (Domain Name System)

  • Typ: Namensauflösung
  • Funktion: Domain → IP-Adresse
  • Record-Typen: A, AAAA, MX, NS, CNAME
  • Port: 53 (UDP/TCP)

HTTP/HTTPS (Hypertext Transfer Protocol)

  • Typ: Anwendungsprotokoll für Web
  • Methoden: GET, POST, PUT, DELETE
  • Status: 200 OK, 404 Not Found, 500 Server Error
  • Port: 80 (HTTP), 443 (HTTPS)

Prüfungsrelevante Stichpunkte

  • Netzwerkprotokolle: Regeln für computergestützte Kommunikation
  • TCP: Verbindungsorientiert, zuverlässig, 3-Wege-Handshake
  • UDP: Verbindungslos, schnell, unzuverlässig, Streaming
  • IP: Paketvermittlung, Routing, IPv4/IPv6
  • DNS: Namensauflösung, Domain → IP-Adresse
  • HTTP/HTTPS: Web-Kommunikation, Request/Response
  • OSI-Modell: 7-Schichten-Modell für Netzwerkkommunikation
  • TCP/IP-Stack: 4-Schichten-Modell, praktische Implementierung
  • IHK-relevant: Grundlage für Netzwerkadministration und -entwicklung

Kernkomponenten

  1. OSI-Modell: Theoretisches 7-Schichten-Modell
  2. TCP/IP-Stack: Praktisches 4-Schichten-Modell
  3. Transportprotokolle: TCP, UDP für Datentransport
  4. Netzwerkprotokolle: IP für Routing und Adressierung
  5. Anwendungsprotokolle: HTTP, DNS, SMTP für Dienste
  6. Port-Nummern: Identifikation von Diensten
  7. Socket-Programmierung: Netzwerk-Kommunikation
  8. Netzwerk-Sicherheit: Firewalls, VPN, TLS

Praxisbeispiele

1. TCP Socket-Programmierung mit Java

import java.io.*;
import java.net.*;
import java.util.concurrent.*;

public class TCPServerDemo {
    
    private static final int PORT = 8080;
    private static final int MAX_CLIENTS = 10;
    
    public static void main(String[] args) {
        System.out.println("=== TCP Server Demo ===");
        
        // Thread Pool für Client-Verbindungen
        ExecutorService threadPool = Executors.newFixedThreadPool(MAX_CLIENTS);
        
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("TCP Server gestartet auf Port " + PORT);
            
            while (true) {
                // Auf Client-Verbindungen warten
                Socket clientSocket = serverSocket.accept();
                System.out.println("Neuer Client verbunden: " + clientSocket.getInetAddress());
                
                // Client in separatem Thread behandeln
                threadPool.execute(new ClientHandler(clientSocket));
            }
            
        } catch (IOException e) {
            System.err.println("Server-Fehler: " + e.getMessage());
        } finally {
            threadPool.shutdown();
        }
    }
    
    // Client-Handler
    static class ClientHandler implements Runnable {
        private final Socket clientSocket;
        
        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }
        
        @Override
        public void run() {
            try (
                BufferedReader in = new BufferedReader(
                    new InputStreamReader(clientSocket.getInputStream()));
                PrintWriter out = new PrintWriter(
                    clientSocket.getOutputStream(), true)
            ) {
                
                String clientAddress = clientSocket.getInetAddress().toString();
                System.out.println("Handler für " + clientAddress + " gestartet");
                
                // Begrüßung senden
                out.println("Willkommen beim TCP Server!");
                out.println("Type 'exit' to disconnect");
                
                // Nachrichten vom Client empfangen und beantworten
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    System.out.println("Nachricht von " + clientAddress + ": " + inputLine);
                    
                    if ("exit".equalsIgnoreCase(inputLine.trim())) {
                        out.println("Goodbye!");
                        break;
                    }
                    
                    // Echo mit Timestamp
                    String response = "Echo: " + inputLine + " [" + 
                                   java.time.LocalDateTime.now() + "]";
                    out.println(response);
                }
                
            } catch (IOException e) {
                System.err.println("Fehler bei Client-Handler: " + e.getMessage());
            } finally {
                try {
                    clientSocket.close();
                    System.out.println("Client-Verbindung geschlossen");
                } catch (IOException e) {
                    System.err.println("Fehler beim Schließen der Verbindung: " + e.getMessage());
                }
            }
        }
    }
    
    // TCP Client
    static class TCPClient {
        private final String hostname;
        private final int port;
        
        public TCPClient(String hostname, int port) {
            this.hostname = hostname;
            this.port = port;
        }
        
        public void start() {
            try (
                Socket socket = new Socket(hostname, port);
                BufferedReader in = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));
                PrintWriter out = new PrintWriter(
                    socket.getOutputStream(), true);
                BufferedReader stdIn = new BufferedReader(
                    new InputStreamReader(System.in))
            ) {
                
                System.out.println("Mit Server verbunden");
                
                // Server-Antwort empfangen
                String serverResponse = in.readLine();
                System.out.println("Server: " + serverResponse);
                
                // Interaktive Kommunikation
                String userInput;
                while ((userInput = stdIn.readLine()) != null) {
                    out.println(userInput);
                    
                    serverResponse = in.readLine();
                    System.out.println("Server: " + serverResponse);
                    
                    if ("exit".equalsIgnoreCase(userInput.trim())) {
                        break;
                    }
                }
                
            } catch (UnknownHostException e) {
                System.err.println("Unbekannter Host: " + hostname);
            } catch (IOException e) {
                System.err.println("I/O Fehler: " + e.getMessage());
            }
        }
    }
    
    // TCP Performance Test
    static class TCPPerformanceTest {
        
        public static void testTCPLatency(String hostname, int port, int iterations) {
            try (Socket socket = new Socket(hostname, port);
                 PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                 BufferedReader in = new BufferedReader(
                     new InputStreamReader(socket.getInputStream()))) {
                
                System.out.println("=== TCP Latency Test ===");
                
                long totalTime = 0;
                
                for (int i = 0; i < iterations; i++) {
                    long startTime = System.nanoTime();
                    
                    out.println("ping");
                    String response = in.readLine();
                    
                    long endTime = System.nanoTime();
                    long latency = (endTime - startTime) / 1_000_000; // ms
                    
                    totalTime += latency;
                    
                    if (i % 10 == 0) {
                        System.out.printf("Ping %d: %dms%n", i + 1, latency);
                    }
                }
                
                double avgLatency = (double) totalTime / iterations;
                System.out.printf("Durchschnittliche Latenz: %.2fms%n", avgLatency);
                
            } catch (IOException e) {
                System.err.println("Fehler bei Latenz-Test: " + e.getMessage());
            }
        }
        
        public static void testTCPThroughput(String hostname, int port, int dataSize) {
            try (Socket socket = new Socket(hostname, port);
                 PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                 BufferedReader in = new BufferedReader(
                     new InputStreamReader(socket.getInputStream()))) {
                
                System.out.println("=== TCP Throughput Test ===");
                
                // Testdaten erstellen
                StringBuilder testData = new StringBuilder();
                for (int i = 0; i < dataSize; i++) {
                    testData.append("A");
                }
                
                long startTime = System.nanoTime();
                
                out.println("throughput:" + testData.toString());
                String response = in.readLine();
                
                long endTime = System.nanoTime();
                long duration = (endTime - startTime) / 1_000_000; // ms
                
                double throughput = (double) dataSize / (duration / 1000.0) / 1024.0; // KB/s
                System.out.printf("Durchsatz: %.2f KB/s (%d Bytes in %dms)%n", 
                                 throughput, dataSize, duration);
                
            } catch (IOException e) {
                System.err.println("Fehler bei Throughput-Test: " + e.getMessage());
            }
        }
    }
    
    // Main für Client-Tests
    public static void main(String[] args) {
        // Server starten
        if (args.length == 0) {
            TCPServerDemo.main(args);
        } else {
            // Client-Tests
            TCPClient client = new TCPClient("localhost", PORT);
            
            // Interaktiver Client
            new Thread(() -> client.start()).start();
            
            // Performance Tests
            try {
                Thread.sleep(2000); // Warten bis Server bereit
                TCPPerformanceTest.testTCPLatency("localhost", PORT, 100);
                TCPPerformanceTest.testTCPThroughput("localhost", PORT, 10240);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

2. UDP Socket-Programmierung mit Python

import socket
import threading
import time
import json
from datetime import datetime

# UDP Server
class UDPServer:
    def __init__(self, host='localhost', port=9999):
        self.host = host
        self.port = port
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.clients = set()
        self.running = False
        
    def start(self):
        """Start des UDP Servers"""
        self.server_socket.bind((self.host, self.port))
        self.running = True
        print(f"UDP Server läuft auf {self.host}:{self.port}")
        
        while self.running:
            try:
                # Daten empfangen
                data, client_address = self.server_socket.recvfrom(2048)
                
                # Client zur Liste hinzufügen
                self.clients.add(client_address)
                
                print(f"Nachricht von {client_address}: {data.decode()}")
                
                # Nachricht an alle Clients senden (Broadcast)
                self.broadcast(data, client_address)
                
            except Exception as e:
                print(f"Fehler beim Empfangen: {e}")
    
    def broadcast(self, message, sender_address):
        """Nachricht an alle Clients senden"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        broadcast_message = f"[{timestamp}] {sender_address[0]}: {message.decode()}"
        
        for client in self.clients:
            if client != sender_address:
                try:
                    self.server_socket.sendto(broadcast_message.encode(), client)
                except Exception as e:
                    print(f"Fehler beim Senden an {client}: {e}")
    
    def stop(self):
        """Server stoppen"""
        self.running = False
        self.server_socket.close()
        print("UDP Server gestoppt")

# UDP Client
class UDPClient:
    def __init__(self, host='localhost', port=9999):
        self.host = host
        self.port = port
        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.running = False
        
    def start(self, username):
        """Start des UDP Clients"""
        self.running = True
        print(f"UDP Client verbunden mit {self.host}:{self.port}")
        
        # Empfangs-Thread starten
        receive_thread = threading.Thread(target=self.receive_messages)
        receive_thread.daemon = True
        receive_thread.start()
        
        try:
            while self.running:
                # Nachricht eingeben
                message = input(f"{username}: ")
                
                if message.lower() == 'exit':
                    break
                
                # Nachricht senden
                full_message = f"{username}: {message}"
                self.client_socket.sendto(full_message.encode(), (self.host, self.port))
                
        except KeyboardInterrupt:
            print("\nClient beendet")
        finally:
            self.stop()
    
    def receive_messages(self):
        """Nachrichten vom Server empfangen"""
        while self.running:
            try:
                data, server = self.client_socket.recvfrom(2048)
                print(f"\r{data.decode()}")
                print("Nachricht: ", end="", flush=True)
                
            except Exception as e:
                if self.running:
                    print(f"Fehler beim Empfangen: {e}")
                break
    
    def stop(self):
        """Client stoppen"""
        self.running = False
        self.client_socket.close()
        print("UDP Client gestoppt")

# UDP Performance Test
class UDPPerformanceTest:
    def __init__(self, host='localhost', port=9999):
        self.host = host
        self.port = port
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
    def test_latency(self, iterations=100):
        """UDP Latenz Test"""
        print(f"=== UDP Latency Test ===")
        
        latencies = []
        
        for i in range(iterations):
            start_time = time.time()
            
            # Ping-Nachricht senden
            self.socket.sendto(b"ping", (self.host, self.port))
            
            # Antwort empfangen
            try:
                data, _ = self.socket.recvfrom(1024)
                end_time = time.time()
                
                latency = (end_time - start_time) * 1000  # ms
                latencies.append(latency)
                
                if i % 10 == 0:
                    print(f"Ping {i+1}: {latency:.2f}ms")
                    
            except socket.timeout:
                print(f"Timeout bei Ping {i+1}")
        
        if latencies:
            avg_latency = sum(latencies) / len(latencies)
            min_latency = min(latencies)
            max_latency = max(latencies)
            
            print(f"\nLatenz-Statistik:")
            print(f"  Durchschnitt: {avg_latency:.2f}ms")
            print(f"  Minimum: {min_latency:.2f}ms")
            print(f"  Maximum: {max_latency:.2f}ms")
    
    def test_throughput(self, data_size=1024, duration=5):
        """UDP Throughput Test"""
        print(f"\n=== UDP Throughput Test ===")
        
        # Testdaten erstellen
        test_data = b'A' * data_size
        
        start_time = time.time()
        packets_sent = 0
        
        while time.time() - start_time < duration:
            try:
                self.socket.sendto(test_data, (self.host, self.port))
                packets_sent += 0
                
                # Kurze Pause um Server nicht zu überlasten
                time.sleep(0.001)
                
            except Exception as e:
                print(f"Fehler beim Senden: {e}")
                break
        
        end_time = time.time()
        total_time = end_time - start_time
        
        throughput = (packets_sent * data_size) / total_time / 1024  # KB/s
        packets_per_second = packets_sent / total_time
        
        print(f"Throughput-Statistik:")
        print(f"  Pakete gesendet: {packets_sent}")
        print(f  "  Gesamtdauer: {total_time:.2f}s")
        print(f"  Pakete/Sekunde: {packets_per_second:.2f}")
        print(f"  Durchsatz: {throughput:.2f} KB/s")
    
    def test_packet_loss(self, packets=1000):
        """UDP Packet Loss Test"""
        print(f"\n=== UDP Packet Loss Test ===")
        
        packets_lost = 0
        
        for i in range(packets):
            try:
                # Sequenzielle Nummer senden
                packet = f"packet_{i}".encode()
                self.socket.sendto(packet, (self.host, self.port))
                
                # Kurze Pause
                time.sleep(0.001)
                
            except Exception as e:
                packets_lost += 1
        
        loss_rate = (packets_lost / packets) * 100
        print(f"Packet Loss Statistik:")
        print(f"  Pakete gesendet: {packets}")
        print(f"  Pakete verloren: {packets_lost}")
        print(f"  Verlustrate: {loss_rate:.2f}%")
    
    def close(self):
        """Socket schließen"""
        self.socket.close()

# UDP Multicast Demo
class UDPMulticastDemo:
    def __init__(self, multicast_group='224.0.0.1', port=5000):
        self.multicast_group = multicast_group
        self.port = port
        
    def create_multicast_sender(self):
        """Multicast Sender erstellen"""
        sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # TTL setzen (wie viele Hops das Paket machen darf)
        ttl = struct.pack('b', 1)
        sender.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
        
        return sender
    
    def create_multicast_receiver(self):
        """Multicast Receiver erstellen"""
        receiver = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # Socket an Multicast-Adresse binden
        receiver.bind(('', self.port))
        
        # Der Multicast-Gruppe beitreten
        group = socket.inet_aton(self.multicast_group)
        receiver.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, group + socket.inet_aton('0.0.0.0'))
        
        return receiver
    
    def send_multicast(self, message):
        """Multicast-Nachricht senden"""
        sender = self.create_multicast_sender()
        
        try:
            sender.sendto(message.encode(), (self.multicast_group, self.port))
            print(f"Multicast gesendet: {message}")
        finally:
            sender.close()
    
    def receive_multicast(self):
        """Multicast-Nachrichten empfangen"""
        receiver = self.create_multicast_receiver()
        
        try:
            print(f"Multicast Receiver lauscht auf {self.multicast_group}:{self.port}")
            
            while True:
                try:
                    data, address = receiver.recvfrom(1024)
                    print(f"Multicast von {address}: {data.decode()}")
                    
                except KeyboardInterrupt:
                    break
                    
        finally:
            # Gruppe verlassen
            group = socket.inet_aton(self.multicast_group)
            receiver.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP, group + socket.inet_aton('0.0.0.0'))
            receiver.close()

# Main für UDP-Demos
def main():
    import sys
    
    if len(sys.argv) > 1:
        mode = sys.argv[1]
        
        if mode == "server":
            # UDP Server starten
            server = UDPServer()
            try:
                server.start()
            except KeyboardInterrupt:
                server.stop()
                
        elif mode == "client":
            # UDP Client starten
            username = input("Ihr Name: ")
            client = UDPClient()
            client.start(username)
            
        elif mode == "performance":
            # Performance Tests
            test = UDPPerformanceTest()
            test.test_latency(100)
            test.test_throughput(1024, 5)
            test.test_packet_loss(1000)
            test.close()
            
        elif mode == "multicast_send":
            # Multicast Sender
            multicast = UDPMulticastDemo()
            while True:
                message = input("Multicast-Nachricht (oder 'exit'): ")
                if message.lower() == 'exit':
                    break
                multicast.send_multicast(message)
                
        elif mode == "multicast_receive":
            # Multicast Receiver
            multicast = UDPMulticastDemo()
            multicast.receive_multicast()
            
        else:
            print("Verwendung: python udp_demo.py [server|client|performance|multicast_send|multicast_receive]")
    else:
        print("Verwendung: python udp_demo.py [server|client|performance|multicast_send|multicast_receive]")

if __name__ == "__main__":
    main()

3. DNS-Abfragen mit verschiedenen Programmiersprachen

import java.net.*;
import java.util.*;

public class DNSLookupDemo {
    
    // Einfache DNS-Abfrage
    public static String dnsLookup(String hostname) {
        try {
            InetAddress address = InetAddress.getByName(hostname);
            return address.getHostAddress();
        } catch (UnknownHostException e) {
            return "Unknown host: " + hostname;
        }
    }
    
    // Reverse DNS-Abfrage (IP → Hostname)
    public static String reverseDNSLookup(String ipAddress) {
        try {
            InetAddress address = InetAddress.getByName(ipAddress);
            return address.getHostName();
        } catch (UnknownHostException e) {
            return "Unknown IP: " + ipAddress;
        }
    }
    
    // Alle IP-Adressen für einen Hostnamen
    public static List<String> getAllIPAddresses(String hostname) {
        List<String> addresses = new ArrayList<>();
        
        try {
            InetAddress[] allAddresses = InetAddress.getAllByName(hostname);
            for (InetAddress addr : allAddresses) {
                addresses.add(addr.getHostAddress());
            }
        } catch (UnknownHostException e) {
            addresses.add("Unknown host: " + hostname);
        }
        
        return addresses;
    }
    
    // DNS-Record-Typen abfragen (vereinfacht)
    public static void dnsLookupWithTypes(String hostname) {
        System.out.println("=== DNS Lookup für " + hostname + " ===");
        
        // A-Record (IPv4)
        String ipv4 = dnsLookup(hostname);
        System.out.println("A-Record (IPv4): " + ipv4);
        
        // AAAA-Record (IPv6)
        try {
            InetAddress ipv6Address = InetAddress.getByName(hostname);
            if (ipv6Address instanceof Inet6Address) {
                System.out.println("AAAA-Record (IPv6): " + ipv6Address.getHostAddress());
            }
        } catch (UnknownHostException e) {
            System.out.println("AAAA-Record (IPv6): Nicht gefunden");
        }
        
        // Reverse Lookup
        if (!ipv4.equals("Unknown host: " + hostname)) {
            String reverse = reverseDNSLookup(ipv4);
            System.out.println("PTR-Record (Reverse): " + reverse);
        }
        
        // MX-Records (Mail Exchange)
        dnsLookupMX(hostname);
        
        // NS-Records (Name Server)
        dnsLookupNS(hostname);
    }
    
    // MX-Records abfragen
    public static void dnsLookupMX(String hostname) {
        try {
            // In der Praxis würde man DNS-Bibliotheken wie dnsjava verwenden
            // Hier zeigen wir das Konzept
            System.out.println("MX-Records: Verwendet DNS-Bibliotheken für vollständige Abfrage");
            
            // Beispiel mit einfacher Logik
            if (hostname.endsWith(".com")) {
                System.out.println("  MX: mail." + hostname + " (Beispiel)");
            }
            
        } catch (Exception e) {
            System.out.println("MX-Records: Fehler bei Abfrage - " + e.getMessage());
        }
    }
    
    // NS-Records abfragen
    public static void dnsLookupNS(String hostname) {
        try {
            System.out.println("NS-Records: Verwendet DNS-Bibliotheken für vollständige Abfrage");
            
            // Beispiel mit einfacher Logik
            String[] commonNS = {"ns1." + hostname, "ns2." + hostname};
            for (String ns : commonNS) {
                System.out.println("  NS: " + ns + " (Beispiel)");
            }
            
        } catch (Exception e) {
            System.out.println("NS-Records: Fehler bei Abfrage - " + e.getMessage());
        }
    }
    
    // DNS-Performance-Test
    public static void dnsPerformanceTest(String hostname, int iterations) {
        System.out.println("=== DNS Performance Test ===");
        
        long totalTime = 0;
        int successfulLookups = 0;
        
        for (int i = 0; i < iterations; i++) {
            long startTime = System.nanoTime();
            
            String result = dnsLookup(hostname);
            
            long endTime = System.nanoTime();
            long duration = (endTime - startTime) / 1_000_000; // ms
            
            if (!result.startsWith("Unknown host")) {
                totalTime += duration;
                successfulLookups++;
            }
            
            if (i % 10 == 0) {
                System.out.printf("Lookup %d: %dms%n", i + 1, duration);
            }
        }
        
        if (successfulLookups > 0) {
            double avgTime = (double) totalTime / successfulLookups;
            System.out.printf("Durchschnittliche DNS-Lookup Zeit: %.2fms%n", avgTime);
            System.out.printf("Erfolgreiche Lookups: %d/%d%n", successfulLookups, iterations);
        }
    }
    
    // DNS-Caching Demo
    public static void dnsCachingDemo(String hostname) {
        System.out.println("=== DNS Caching Demo ===");
        
        // Erster Lookup (Cache-Miss)
        long start = System.nanoTime();
        String result1 = dnsLookup(hostname);
        long firstLookup = (System.nanoTime() - start) / 1_000_000;
        
        // Zweiter Lookup (Cache-Hit)
        start = System.nanoTime();
        String result2 = dnsLookup(hostname);
        long secondLookup = (System.nanoTime() - start) / 1_000_000;
        
        System.out.println("Erster Lookup: " + firstLookup + "ms");
        System.out.println("Zweiter Lookup: " + secondLookup + "ms");
        
        if (secondLookup < firstLookup) {
            System.out.println("DNS-Caching aktiv (zweiter Lookup schneller)");
        } else {
            System.out.println("Kein DNS-Caching erkannt");
        }
        
        // Ergebnisse vergleichen
        System.out.println("Ergebnis 1: " + result1);
        System.out.println("Ergebnis 2: " + result2);
        System.out.println("Ergebnisse gleich: " + result1.equals(result2));
    }
    
    // IPv6 Support Test
    public static void ipv6SupportTest(String hostname) {
        System.out.println("=== IPv6 Support Test ===");
        
        try {
            // IPv6-Adresse auflösen
            InetAddress[] addresses = InetAddress.getAllByName(hostname);
            
            boolean hasIPv4 = false;
            boolean hasIPv6 = false;
            
            for (InetAddress addr : addresses) {
                if (addr instanceof Inet4Address) {
                    hasIPv4 = true;
                    System.out.println("IPv4: " + addr.getHostAddress());
                } else if (addr instanceof Inet6Address) {
                    hasIPv6 = true;
                    System.out.println("IPv6: " + addr.getHostAddress());
                }
            }
            
            System.out.println("IPv4 Support: " + (hasIPv4 ? "Ja" : "Nein"));
            System.out.println("IPv6 Support: " + (hasIPv6 ? "Ja" : "Nein"));
            
        } catch (UnknownHostException e) {
            System.out.println("IPv6 Support Test fehlgeschlagen: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        String hostname = "google.com";
        
        if (args.length > 0) {
            hostname = args[0];
        }
        
        // Verschiedene DNS-Abfragen
        dnsLookupWithTypes(hostname);
        
        // Performance-Test
        dnsPerformanceTest(hostname, 50);
        
        // Caching-Demo
        dnsCachingDemo(hostname);
        
        // IPv6 Support Test
        ipv6SupportTest(hostname);
    }
}

4. HTTP/HTTPS Client mit verschiedenen Features

import requests
import json
import time
import ssl
import urllib3
from urllib3.util.retry import Retry
from datetime import datetime

# HTTP Client mit erweiterten Features
class HTTPClient:
    def __init__(self):
        self.session = requests.Session()
        self.setup_session()
        
    def setup_session(self):
        """Session konfigurieren"""
        # Retry-Strategie
        retry_strategy = Retry(
            total=3,
            backoff_factor=1,
            status_forcelist=[429, 500, 502, 503, 504],
            allowed_methods=["HEAD", "GET", "OPTIONS"]
        )
        
        adapter = urllib3.HTTPAdapter(max_retries=retry_strategy)
        self.session.mount("https://", adapter)
        self.session.mount("http://", adapter)
        
        # Headers
        self.session.headers.update({
            'User-Agent': 'HTTPClient-Demo/1.0',
            'Accept': 'application/json',
            'Accept-Language': 'de-DE,de;q=0.9,en;q=0.8',
            'Cache-Control': 'no-cache'
        })
        
        # Timeout
        self.session.timeout = 30
        
        print("HTTP Client konfiguriert")
    
    def get_request(self, url, params=None):
        """GET-Request mit Fehlerbehandlung"""
        try:
            print(f"GET Request: {url}")
            
            start_time = time.time()
            response = self.session.get(url, params=params)
            end_time = time.time()
            
            self.print_response_info(response, end_time - start_time)
            return response
            
        except requests.exceptions.RequestException as e:
            print(f"GET Request fehlgeschlagen: {e}")
            return None
    
    def post_request(self, url, data=None, json_data=None):
        """POST-Request mit Daten"""
        try:
            print(f"POST Request: {url}")
            
            if json_data:
                print(f"JSON-Daten: {json.dumps(json_data, indent=2)}")
            
            start_time = time.time()
            
            if json_data:
                response = self.session.post(url, json=json_data)
            else:
                response = self.session.post(url, data=data)
            
            end_time = time.time()
            
            self.print_response_info(response, end_time - start_time)
            return response
            
        except requests.exceptions.RequestException as e:
            print(f"POST Request fehlgeschlagen: {e}")
            return None
    
    def print_response_info(self, response, duration):
        """Response-Informationen ausgeben"""
        print(f"Status Code: {response.status_code}")
        print(f"Response Time: {duration:.2f}s")
        print(f"Content-Type: {response.headers.get('Content-Type', 'N/A')}")
        print(f"Content-Length: {response.headers.get('Content-Length', 'N/A')}")
        
        # Headers ausgeben
        if response.headers:
            print("Response Headers:")
            for key, value in response.headers.items():
                print(f"  {key}: {value}")
    
    def test_http_methods(self, url):
        """Verschiedene HTTP-Methoden testen"""
        print(f"=== HTTP Methods Test für {url} ===")
        
        # GET
        print("\n--- GET ---")
        response = self.get_request(url)
        
        # HEAD
        print("\n--- HEAD ---")
        try:
            response = self.session.head(url)
            print(f"HEAD Status: {response.status_code}")
            print(f"HEAD Headers: {dict(response.headers)}")
        except Exception as e:
            print(f"HEAD Request fehlgeschlagen: {e}")
        
        # OPTIONS
        print("\n--- OPTIONS ---")
        try:
            response = self.session.options(url)
            print(f"OPTIONS Status: {response.status_code}")
            allowed_methods = response.headers.get('Allow', 'N/A')
            print(f"Erlaubte Methoden: {allowed_methods}")
        except Exception as e:
            print(f"OPTIONS Request fehlgeschlagen: {e}")
    
    def test_https_features(self, url):
        """HTTPS-Features testen"""
        print(f"=== HTTPS Features Test für {url} ===")
        
        try:
            # SSL-Zertifikat-Informationen
            response = self.session.get(url)
            
            # SSL-Informationen ausgeben
            cert_info = response.raw._connection.peer.cert
            if cert_info:
                print("SSL-Zertifikat-Informationen:")
                for cert in cert_info:
                    print(f"  Subject: {cert.subject}")
                    print(f"  Issuer: {cert.issuer}")
                    print(f"  Valid from: {cert.not_valid_before}")
                    print(f"  Valid until: {cert.not_valid_after}")
                    print(f"  Serial: {cert.serial_number}")
            
            # TLS-Version
            tls_version = response.raw._connection.tls_version
            print(f"TLS-Version: {tls_version}")
            
            # Cipher Suite
            cipher_suite = response.raw._connection.cipher
            print(f"Cipher Suite: {cipher_suite}")
            
        except Exception as e:
            print(f"HTTPS Features Test fehlgeschlagen: {e}")
    
    def test_authentication(self, url, username, password):
        """HTTP-Authentifizierung testen"""
        print(f"=== Authentication Test für {url} ===")
        
        # Basic Authentication
        try:
            from requests.auth import HTTPBasicAuth
            
            auth = HTTPBasicAuth(username, password)
            response = self.session.get(url, auth=auth)
            
            print(f"Basic Auth Status: {response.status_code}")
            
            if response.status_code == 200:
                print("Basic Authentication erfolgreich")
            else:
                print("Basic Authentication fehlgeschlagen")
                
        except Exception as e:
            print(f"Authentication Test fehlgeschlagen: {e}")
    
    def test_cookies(self, url):
        """Cookie-Handling testen"""
        print(f"=== Cookie Test für {url} ===")
        
        try:
            # Erste Request ohne Cookies
            response1 = self.session.get(url)
            print(f"Erster Request Status: {response1.status_code}")
            print(f"Cookies nach erstem Request: {len(self.session.cookies)}")
            
            # Zweiter Request mit Cookies
            response2 = self.session.get(url)
            print(f"Zweiter Request Status: {response2.status_code}")
            print(f"Cookies nach zweitem Request: {len(self.session.cookies)}")
            
            # Cookie-Informationen
            if self.session.cookies:
                print("Cookie-Details:")
                for cookie in self.session.cookies:
                    print(f"  {cookie.name}: {cookie.value}")
                    print(f"    Domain: {cookie.domain}")
                    print(f"    Path: {cookie.path}")
                    print(f"    Secure: {cookie.secure}")
                    print(f"    HttpOnly: {cookie.has_attr('HttpOnly')}")
            
        except Exception as e:
            print(f"Cookie Test fehlgeschlagen: {e}")
    
    def test_redirects(self, url):
        """Redirect-Handling testen"""
        print(f"=== Redirect Test für {url} ===")
        
        try:
            # Redirects nicht folgen
            response = self.session.get(url, allow_redirects=False)
            print(f"Status ohne Redirects: {response.status_code}")
            
            if 300 <= response.status_code < 400:
                location = response.headers.get('Location', 'N/A')
                print(f"Redirect zu: {location}")
            
            # Redirects folgen
            response = self.session.get(url, allow_redirects=True)
            print(f"Status mit Redirects: {response.status_code}")
            print(f"Final URL: {response.url}")
            
            # Redirect-Verlauf
            if hasattr(response.history, '__iter__'):
                print("Redirect-Verlauf:")
                for i, resp in enumerate(response.history):
                    print(f"  {i+1}. {resp.status_code} -> {resp.url}")
            
        except Exception as e:
            print(f"Redirect Test fehlgeschlagen: {e}")
    
    def test_download(self, url, save_path=None):
        """Datei-Download testen"""
        print(f"=== Download Test für {url} ===")
        
        try:
            response = self.session.get(url, stream=True)
            
            content_length = int(response.headers.get('content-length', 0))
            print(f"Dateigröße: {content_length} bytes")
            
            if save_path:
                with open(save_path, 'wb') as f:
                    downloaded = 0
                    chunk_size = 8192
                    
                    for chunk in response.iter_content(chunk_size=chunk_size):
                        f.write(chunk)
                        downloaded += chunk_size
                        
                        # Progress anzeigen
                        progress = (downloaded / content_length) * 100 if content_length > 0 else 0
                        print(f"\rDownload: {progress:.1f}%", end="", flush=True)
                
                print(f"\nDatei gespeichert: {save_path}")
            
        except Exception as e:
            print(f"Download fehlgeschlagen: {e}")
    
    def performance_test(self, url, iterations=10):
        """Performance-Test"""
        print(f"=== Performance Test für {url} ===")
        
        times = []
        
        for i in range(iterations):
            try:
                start_time = time.time()
                response = self.session.get(url)
                end_time = time.time()
                
                duration = end_time - start_time
                times.append(duration)
                
                if i % 5 == 0:
                    print(f"Request {i+1}: {duration:.3f}s")
                
            except Exception as e:
                print(f"Request {i+1} fehlgeschlagen: {e}")
        
        if times:
            avg_time = sum(times) / len(times)
            min_time = min(times)
            max_time = max(times)
            
            print(f"\nPerformance-Statistik:")
            print(f"  Requests: {len(times)}")
            print(f"  Durchschnitt: {avg_time:.3f}s")
            print(f"  Minimum: {min_time:.3f}s")
            print(f"  Maximum: {max_time:.3f}s")
            print(f"  Requests/Sekunde: {1/avg_time:.2f}")

# API-Client für REST-APIs
class APIClient(HTTPClient):
    def __init__(self, base_url):
        super().__init__()
        self.base_url = base_url.rstrip('/')
        
        # API-spezifische Headers
        self.session.headers.update({
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        })
    
    def get_resource(self, resource, params=None):
        """GET Resource"""
        url = f"{self.base_url}/{resource.lstrip('/')}"
        return self.get_request(url, params)
    
    def create_resource(self, resource, data):
        """POST Resource"""
        url = f"{self.base_url}/{resource.lstrip('/')}"
        return self.post_request(url, json_data=data)
    
    def update_resource(self, resource, data):
        """PUT Resource"""
        url = f"{self.base_url}/{resource.lstrip('/')}"
        try:
            response = self.session.put(url, json=data)
            self.print_response_info(response, 0)
            return response
        except Exception as e:
            print(f"PUT Request fehlgeschlagen: {e}")
            return None
    
    def delete_resource(self, resource):
        """DELETE Resource"""
        url = f"{self.base_url}/{resource.lstrip('/')}"
        try:
            response = self.session.delete(url)
            self.print_response_info(response, 0)
            return response
        except Exception as e:
            print(f"DELETE Request fehlgeschlagen: {e}")
            return None

# Main für HTTP-Demos
def main():
    import sys
    
    # HTTP Client Demo
    client = HTTPClient()
    
    # HTTP-Methoden Test
    client.test_http_methods("https://httpbin.org")
    
    # HTTPS Features Test
    client.test_https_features("https://google.com")
    
    # Redirect Test
    client.test_redirects("http://httpbin.org/redirect/1")
    
    # Cookie Test
    client.test_cookies("https://httpbin.org/cookies/set/test/value")
    
    # Performance Test
    client.performance_test("https://httpbin.org/get", 20)
    
    # API Client Demo
    api_client = APIClient("https://jsonplaceholder.typicode.com")
    
    # GET Users
    users_response = api_client.get_resource("/users")
    if users_response:
        print(f"Users: {users_response.json()}")
    
    # Create Post
    new_post = {
        "title": "Test Post",
        "body": "Test Body",
        "userId": 1
    }
    create_response = api_client.create_resource("/posts", new_post)
    
    # Download Test
    client.test_download("https://httpbin.org/bytes/1024", "test_download.bin")

if __name__ == "__main__":
    main()

OSI-Modell vs TCP/IP-Stack

OSI-Modell (7 Schichten)

SchichtNameFunktionBeispiele
7ApplicationAnwendungsprotokolleHTTP, FTP, SMTP
6PresentationDatenumwandlungSSL/TLS, JPEG
5SessionSitzungsverwaltungNetBIOS, RPC
4TransportEnd-to-End-KommunikationTCP, UDP
3NetworkRouting und AdressierungIP, ICMP
2Data LinkFrame-ÜbertragungEthernet, WiFi
1PhysicalBit-ÜbertragungKabel, Funk

TCP/IP-Stack (4 Schichten)

SchichtNameOSI-EntsprechungProtokolle
4Application5-7HTTP, FTP, DNS
3Transport4TCP, UDP
2Internet3IP, ICMP
1Network Access1-2Ethernet, WiFi

Wichtige Port-Nummern

Well-Known Ports (0-1023)

PortProtokollDienst
20FTPFile Transfer (Data)
21FTPFile Transfer (Control)
22SSHSecure Shell
23TelnetRemote Terminal
25SMTPE-Mail
53DNSDomain Name System
80HTTPWeb (unverschlüsselt)
110POP3E-Mail (Post Office)
143IMAPE-Mail (Internet Message)
443HTTPSWeb (verschlüsselt)
993IMAPSIMAP over SSL
995POP3SPOP3 over SSL

Registered Ports (1024-49151)

PortProtokollDienst
3306MySQLDatenbank
5432PostgreSQLDatenbank
8080HTTP-AltWeb (alternativ)
8443HTTPS-AltWeb (alternativ)
27017MongoDBNoSQL-Datenbank

TCP vs UDP Vergleich

EigenschaftTCPUDP
VerbindungVerbindungsorientiertVerbindungslos
ZuverlässigkeitGarantiertNicht garantiert
ReihenfolgeGarantiertNicht garantiert
FlusskontrolleJaNein
FehlerkorrekturJaNein
OverheadHochNiedrig
GeschwindigkeitLangsamerSchneller
AnwendungWeb, E-MailStreaming, Gaming

HTTP-Statuscodes Übersicht

1xx Informational

  • 100 Continue: Fortsetzung
  • 101 Switching Protocols: Protokoll-Wechsel

2xx Success

  • 200 OK: Erfolgreich
  • 201 Created: Erstellt
  • 204 No Content: Kein Inhalt

3xx Redirection

  • 301 Moved Permanently: Permanent verschoben
  • 302 Found: Temporär verschoben
  • 304 Not Modified: Nicht verändert

4xx Client Error

  • 400 Bad Request: Ungültige Anfrage
  • 401 Unauthorized: Nicht autorisiert
  • 403 Forbidden: Verboten
  • 404 Not Found: Nicht gefunden
  • 429 Too Many Requests: Zu viele Anfragen

5xx Server Error

  • 500 Internal Server Error: Interner Serverfehler
  • 502 Bad Gateway: Gateway-Fehler
  • 503 Service Unavailable: Dienst nicht verfügbar

DNS-Record-Typen

TypBeschreibungBeispiel
AIPv4-Adresseexample.com → 93.184.216.34
AAAAIPv6-Adresseexample.com → 2606:2800:220:1
MXMail Exchangeexample.com → mail.example.com
NSName Serverexample.com → ns1.example.com
CNAMECanonical Namewww.example.com → example.com
TXTText-Informationexample.com → “v=spf1 include:_spf.google.com ~all”
PTRPointer (Reverse)93.184.216.34 → example.com

Socket-Programmierung Grundlagen

TCP Socket Lifecycle

// Server
1. ServerSocket erstellen
2. Auf Verbindung warten (accept)
3. InputStream/OutputStream erstellen
4. Daten austauschen
5. Verbindung schließen

// Client
1. Socket erstellen
2. Mit Server verbinden
3. InputStream/OutputStream erstellen
4. Daten austauschen
5. Verbindung schließen

UDP Socket Lifecycle

// Server
1. DatagramSocket erstellen
2. Auf Pakete warten (receive)
3. Paket verarbeiten
4. Antwort senden (send)

// Client
1. DatagramSocket erstellen
2. Paket senden (send)
3. Auf Antwort warten (receive)
4. Socket schließen

Vorteile und Nachteile

Vorteile von Netzwerkprotokollen

  • Standardisierung: Interoperabilität zwischen Systemen
  • Skalierbarkeit: Unterstützung für große Netzwerke
  • Zuverlässigkeit: Fehlerbehandlung und Wiederherstellung
  • Flexibilität: Verschiedene Protokolle für verschiedene Zwecke

Nachteile

  • Komplexität: Viele Schichten und Protokolle
  • Overhead: Zusätzliche Daten für Protokoll-Informationen
  • Sicherheit: Angriffsflächen für Hacker
  • Performance: Netzwerk-Latenzen

Häufige Prüfungsfragen

  1. Was ist der Unterschied zwischen TCP und UDP? TCP ist verbindungsorientiert und zuverlässig, UDP ist verbindungslos und schnell aber unzuverlässig.

  2. Erklären Sie das OSI-Modell! Das OSI-Modell beschreibt 7 Schichten für Netzwerkkommunikation von Physical bis Application.

  3. Was ist DNS und wie funktioniert es? DNS übersetzt Domain-Namen in IP-Adressen und umgekehrt über hierarchische Namenserver.

  4. Wann verwendet man HTTP vs HTTPS? HTTP für unverschlüsselte Kommunikation, HTTPS für verschlüsselte Kommunikation mit SSL/TLS.

Wichtigste Quellen

  1. https://www.ietf.org/rfc/rfc791.html (TCP)
  2. https://www.ietf.org/rfc/rfc768.html (UDP)
  3. https://www.ietf.org/rfc/rfc1035.html (DNS)
  4. https://www.ietf.org/rfc/rfc2616.html (HTTP/1.1)
Zurück zum Blog
Share: