Skip to content
IRC-Coding IRC-Coding
Network Protocols TCP UDP IP DNS HTTP HTTPS OSI Model TCP IP Stack

Network Protocols: TCP, UDP, IP, DNS, HTTP/HTTPS

Learn network protocols fundamentals: TCP, UDP, IP, DNS, HTTP/HTTPS. Understand OSI model and TCP/IP stack with practical examples.

S

schutzgeist

2 min read
Network Protocols: TCP, UDP, IP, DNS, HTTP/HTTPS

Network Protocols: TCP, UDP, IP, DNS, HTTP/HTTPS & OSI/TCP-IP Models

This post is a comprehensive introduction to network protocols – including TCP, UDP, IP, DNS, HTTP/HTTPS, OSI model and TCP/IP stack with practical examples.

In a Nutshell

Network protocols regulate communication between computers. TCP/IP is the fundamental protocol stack, OSI describes 7 layers, HTTP/HTTPS enable web communication and DNS resolves names to IPs.

Compact Technical Description

Network protocols are standardized rules and conventions for data communication between computers in a network.

Important Protocols:

TCP (Transmission Control Protocol)

  • Type: Connection-oriented, reliable
  • Features: 3-way handshake, flow control, error correction
  • Application: Web, email, file transfer
  • Port: 80 (HTTP), 443 (HTTPS), 25 (SMTP)

UDP (User Datagram Protocol)

  • Type: Connectionless, unreliable
  • Features: Simple, fast, no guarantees
  • Application: Streaming, gaming, DNS
  • Port: 53 (DNS), 123 (NTP), 67 (DHCP)

IP (Internet Protocol)

  • Type: Packet switching, routing
  • Versions: IPv4 (32 bit), IPv6 (128 bit)
  • Features: Addressing, fragmentation
  • Application: Foundation for Internet

DNS (Domain Name System)

  • Type: Name resolution
  • Function: Domain → IP address
  • Record Types: A, AAAA, MX, NS, CNAME
  • Port: 53 (UDP/TCP)

HTTP/HTTPS (Hypertext Transfer Protocol)

  • Type: Application protocol for web
  • Methods: GET, POST, PUT, DELETE
  • Status: 200 OK, 404 Not Found, 500 Server Error
  • Port: 80 (HTTP), 443 (HTTPS)

Exam-Relevant Key Points

  • Network Protocols: Rules for computer-based communication
  • TCP: Connection-oriented, reliable, 3-way handshake
  • UDP: Connectionless, fast, unreliable, streaming
  • IP: Packet switching, routing, IPv4/IPv6
  • DNS: Name resolution, domain → IP address
  • HTTP/HTTPS: Web communication, request/response
  • OSI Model: 7-layer model for network communication
  • TCP/IP Stack: 4-layer model, practical implementation
  • IHK-relevant: Foundation for network administration and development

Core Components

  1. OSI Model: Theoretical 7-layer model
  2. TCP/IP Stack: Practical 4-layer model
  3. Transport Protocols: TCP, UDP for data transport
  4. Network Protocols: IP for routing and addressing
  5. Application Protocols: HTTP, DNS, SMTP for services
  6. Port Numbers: Identification of services
  7. Socket Programming: Network communication
  8. Network Security: Firewalls, VPN, TLS

Practical Examples

1. TCP Socket Programming with 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 for client connections
        ExecutorService threadPool = Executors.newFixedThreadPool(MAX_CLIENTS);
        
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("TCP Server started on port " + PORT);
            
            while (true) {
                // Wait for client connections
                Socket clientSocket = serverSocket.accept();
                System.out.println("New client connected: " + clientSocket.getInetAddress());
                
                // Handle client in separate thread
                threadPool.execute(new ClientHandler(clientSocket));
            }
            
        } catch (IOException e) {
            System.err.println("Server error: " + 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 for " + clientAddress + " started");
                
                // Send greeting
                out.println("Welcome to TCP Server!");
                out.println("Type 'exit' to disconnect");
                
                // Receive and respond to messages from client
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    System.out.println("Message from " + clientAddress + ": " + inputLine);
                    
                    if ("exit".equalsIgnoreCase(inputLine.trim())) {
                        out.println("Goodbye!");
                        break;
                    }
                    
                    // Echo with timestamp
                    String response = "Echo: " + inputLine + " [" + 
                                   java.time.LocalDateTime.now() + "]";
                    out.println(response);
                }
                
            } catch (IOException e) {
                System.err.println("Error in client handler: " + e.getMessage());
            } finally {
                try {
                    clientSocket.close();
                    System.out.println("Client connection closed");
                } catch (IOException e) {
                    System.err.println("Error closing connection: " + 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("Connected to server");
                
                // Receive server response
                String serverResponse = in.readLine();
                System.out.println("Server: " + serverResponse);
                
                // Interactive communication
                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("Unknown host: " + hostname);
            } catch (IOException e) {
                System.err.println("I/O error: " + 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("Average latency: %.2fms%n", avgLatency);
                
            } catch (IOException e) {
                System.err.println("Error in latency 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 ===");
                
                // Create test data
                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("Throughput: %.2f KB/s (%d bytes in %dms)%n", 
                                 throughput, dataSize, duration);
                
            } catch (IOException e) {
                System.err.println("Error in throughput test: " + e.getMessage());
            }
        }
    }
    
    // Main for client tests
    public static void main(String[] args) {
        // Start server
        if (args.length == 0) {
            TCPServerDemo.main(args);
        } else {
            // Client tests
            TCPClient client = new TCPClient("localhost", PORT);
            
            // Interactive client
            new Thread(() -> client.start()).start();
            
            // Performance tests
            try {
                Thread.sleep(2000); // Wait until server is ready
                TCPPerformanceTest.testTCPLatency("localhost", PORT, 100);
                TCPPerformanceTest.testTCPThroughput("localhost", PORT, 10240);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

2. UDP Socket Programming with 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 of the UDP server"""
        self.server_socket.bind((self.host, self.port))
        self.running = True
        print(f"UDP Server running on {self.host}:{self.port}")
        
        while self.running:
            try:
                # Receive data
                data, client_address = self.server_socket.recvfrom(2048)
                
                # Add client to list
                self.clients.add(client_address)
                
                print(f"Message from {client_address}: {data.decode()}")
                
                # Send message to all clients (broadcast)
                self.broadcast(data, client_address)
                
            except Exception as e:
                print(f"Error receiving: {e}")
    
    def broadcast(self, message, sender_address):
        """Send message to all clients"""
        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"Error sending to {client}: {e}")
    
    def stop(self):
        """Stop server"""
        self.running = False
        self.server_socket.close()
        print("UDP Server stopped")

# 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 of the UDP client"""
        self.running = True
        print(f"UDP Client connected to {self.host}:{self.port}")
        
        # Start receive thread
        receive_thread = threading.Thread(target=self.receive_messages)
        receive_thread.daemon = True
        receive_thread.start()
        
        try:
            while self.running:
                # Enter message
                message = input(f"{username}: ")
                
                if message.lower() == 'exit':
                    break
                
                # Send message
                full_message = f"{username}: {message}"
                self.client_socket.sendto(full_message.encode(), (self.host, self.port))
                
        except KeyboardInterrupt:
            print("\nClient terminated")
        finally:
            self.stop()
    
    def receive_messages(self):
        """Receive messages from server"""
        while self.running:
            try:
                data, server = self.client_socket.recvfrom(2048)
                print(f"\r{data.decode()}")
                print("Message: ", end="", flush=True)
                
            except Exception as e:
                if self.running:
                    print(f"Error receiving: {e}")
                break
    
    def stop(self):
        """Stop client"""
        self.running = False
        self.client_socket.close()
        print("UDP Client stopped")

# 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 latency test"""
        print(f"=== UDP Latency Test ===")
        
        latencies = []
        
        for i in range(iterations):
            start_time = time.time()
            
            # Send ping message
            self.socket.sendto(b"ping", (self.host, self.port))
            
            # Receive response
            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 at ping {i+1}")
        
        if latencies:
            avg_latency = sum(latencies) / len(latencies)
            min_latency = min(latencies)
            max_latency = max(latencies)
            
            print(f"\nLatency statistics:")
            print(f"  Average: {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 ===")
        
        # Create test data
        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
                
                # Brief pause to not overload server
                time.sleep(0.001)
                
            except Exception as e:
                print(f"Error sending: {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 statistics:")
        print(f"  Packets sent: {packets_sent}")
        print(f"  Total duration: {total_time:.2f}s")
        print(f"  Packets/second: {packets_per_second:.2f}")
        print(f"  Throughput: {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:
                # Send sequential number
                packet = f"packet_{i}".encode()
                self.socket.sendto(packet, (self.host, self.port))
                
                # Brief pause
                time.sleep(0.001)
                
            except Exception as e:
                packets_lost += 1
        
        loss_rate = (packets_lost / packets) * 100
        print(f"Packet loss statistics:")
        print(f"  Packets sent: {packets}")
        print(f"  Packets lost: {packets_lost}")
        print(f"  Loss rate: {loss_rate:.2f}%")
    
    def close(self):
        """Close socket"""
        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):
        """Create multicast sender"""
        sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # Set TTL (how many hops the packet is allowed to make)
        ttl = struct.pack('b', 1)
        sender.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
        
        return sender
    
    def create_multicast_receiver(self):
        """Create multicast receiver"""
        receiver = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # Bind socket to multicast address
        receiver.bind(('', self.port))
        
        # Join the multicast group
        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):
        """Send multicast message"""
        sender = self.create_multicast_sender()
        
        try:
            sender.sendto(message.encode(), (self.multicast_group, self.port))
            print(f"Multicast sent: {message}")
        finally:
            sender.close()
    
    def receive_multicast(self):
        """Receive multicast messages"""
        receiver = self.create_multicast_receiver()
        
        try:
            print(f"Multicast receiver listening on {self.multicast_group}:{self.port}")
            
            while True:
                try:
                    data, address = receiver.recvfrom(1024)
                    print(f"Multicast from {address}: {data.decode()}")
                    
                except KeyboardInterrupt:
                    break
                    
        finally:
            # Leave group
            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 for UDP demos
def main():
    import sys
    
    if len(sys.argv) > 1:
        mode = sys.argv[1]
        
        if mode == "server":
            # Start UDP server
            server = UDPServer()
            try:
                server.start()
            except KeyboardInterrupt:
                server.stop()
                
        elif mode == "client":
            # Start UDP client
            username = input("Your 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 message (or 'exit'): ")
                if message.lower() == 'exit':
                    break
                multicast.send_multicast(message)
                
        elif mode == "multicast_receive":
            # Multicast receiver
            multicast = UDPMulticastDemo()
            multicast.receive_multicast()
            
        else:
            print("Usage: python udp_demo.py [server|client|performance|multicast_send|multicast_receive]")
    else:
        print("Usage: python udp_demo.py [server|client|performance|multicast_send|multicast_receive]")

if __name__ == "__main__":
    main()

3. DNS Queries with Different Programming Languages

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

public class DNSLookupDemo {
    
    // Simple DNS query
    public static String dnsLookup(String hostname) {
        try {
            InetAddress address = InetAddress.getByName(hostname);
            return address.getHostAddress();
        } catch (UnknownHostException e) {
            return "Unknown host: " + hostname;
        }
    }
    
    // Reverse DNS query (IP → Hostname)
    public static String reverseDNSLookup(String ipAddress) {
        try {
            InetAddress address = InetAddress.getByName(ipAddress);
            return address.getHostName();
        } catch (UnknownHostException e) {
            return "Unknown IP: " + ipAddress;
        }
    }
    
    // All IP addresses for a hostname
    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;
    }
    
    // Query DNS record types (simplified)
    public static void dnsLookupWithTypes(String hostname) {
        System.out.println("=== DNS Lookup for " + 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): Not found");
        }
        
        // 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);
    }
    
    // Query MX records
    public static void dnsLookupMX(String hostname) {
        try {
            // In practice, one would use DNS libraries like dnsjava
            // Here we demonstrate the concept
            System.out.println("MX records: Uses DNS libraries for complete query");
            
            // Example with simple logic
            if (hostname.endsWith(".com")) {
                System.out.println("  MX: mail." + hostname + " (Example)");
            }
            
        } catch (Exception e) {
            System.out.println("MX records: Error during query - " + e.getMessage());
        }
    }
    
    // Query NS records
    public static void dnsLookupNS(String hostname) {
        try {
            System.out.println("NS records: Uses DNS libraries for complete query");
            
            // Example with simple logic
            String[] commonNS = {"ns1." + hostname, "ns2." + hostname};
            for (String ns : commonNS) {
                System.out.println("  NS: " + ns + " (Example)");
            }
            
        } catch (Exception e) {
            System.out.println("NS records: Error during query - " + 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("Average DNS lookup time: %.2fms%n", avgTime);
            System.out.printf("Successful lookups: %d/%d%n", successfulLookups, iterations);
        }
    }
    
    // DNS caching demo
    public static void dnsCachingDemo(String hostname) {
        System.out.println("=== DNS Caching Demo ===");
        
        // First lookup (cache miss)
        long start = System.nanoTime();
        String result1 = dnsLookup(hostname);
        long firstLookup = (System.nanoTime() - start) / 1_000_000;
        
        // Second lookup (cache hit)
        start = System.nanoTime();
        String result2 = dnsLookup(hostname);
        long secondLookup = (System.nanoTime() - start) / 1_000_000;
        
        System.out.println("First lookup: " + firstLookup + "ms");
        System.out.println("Second lookup: " + secondLookup + "ms");
        
        if (secondLookup < firstLookup) {
            System.out.println("DNS caching active (second lookup faster)");
        } else {
            System.out.println("No DNS caching detected");
        }
        
        // Compare results
        System.out.println("Result 1: " + result1);
        System.out.println("Result 2: " + result2);
        System.out.println("Results equal: " + result1.equals(result2));
    }
    
    // IPv6 support test
    public static void ipv6SupportTest(String hostname) {
        System.out.println("=== IPv6 Support Test ===");
        
        try {
            // Resolve IPv6 address
            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 ? "Yes" : "No"));
            System.out.println("IPv6 support: " + (hasIPv6 ? "Yes" : "No"));
            
        } catch (UnknownHostException e) {
            System.out.println("IPv6 support test failed: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        String hostname = "google.com";
        
        if (args.length > 0) {
            hostname = args[0];
        }
        
        // Various DNS queries
        dnsLookupWithTypes(hostname);
        
        // Performance test
        dnsPerformanceTest(hostname, 50);
        
        // Caching demo
        dnsCachingDemo(hostname);
        
        // IPv6 support test
        ipv6SupportTest(hostname);
    }
}

4. HTTP/HTTPS Client with various features

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

# HTTP Client with advanced features
class HTTPClient:
    def __init__(self):
        self.session = requests.Session()
        self.setup_session()
        
    def setup_session(self):
        """Configure session"""
        # Retry strategy
        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 configured")
    
    def get_request(self, url, params=None):
        """GET request with error handling"""
        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 failed: {e}")
            return None
    
    def post_request(self, url, data=None, json_data=None):
        """POST request with data"""
        try:
            print(f"POST Request: {url}")
            
            if json_data:
                print(f"JSON data: {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 failed: {e}")
            return None
    
    def print_response_info(self, response, duration):
        """Print response information"""
        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')}")
        
        # Print headers
        if response.headers:
            print("Response Headers:")
            for key, value in response.headers.items():
                print(f"  {key}: {value}")
    
    def test_http_methods(self, url):
        """Test various HTTP methods"""
        print(f"=== HTTP Methods Test for {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 failed: {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"Allowed methods: {allowed_methods}")
        except Exception as e:
            print(f"OPTIONS Request failed: {e}")
    
    def test_https_features(self, url):
        """Test HTTPS features"""
        print(f"=== HTTPS Features Test for {url} ===")
        
        try:
            # SSL certificate information
            response = self.session.get(url)
            
            # Print SSL information
            cert_info = response.raw._connection.peer.cert
            if cert_info:
                print("SSL Certificate Information:")
                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 failed: {e}")
    
    def test_authentication(self, url, username, password):
        """Test HTTP authentication"""
        print(f"=== Authentication Test for {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 successful")
            else:
                print("Basic Authentication failed")
                
        except Exception as e:
            print(f"Authentication Test failed: {e}")
    
    def test_cookies(self, url):
        """Test cookie handling"""
        print(f"=== Cookie Test for {url} ===")
        
        try:
            # First request without cookies
            response1 = self.session.get(url)
            print(f"First request status: {response1.status_code}")
            print(f"Cookies after first request: {len(self.session.cookies)}")
            
            # Second request with cookies
            response2 = self.session.get(url)
            print(f"Second request status: {response2.status_code}")
            print(f"Cookies after second request: {len(self.session.cookies)}")
            
            # Cookie information
            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 failed: {e}")
    
    def test_redirects(self, url):
        """Test redirect handling"""
        print(f"=== Redirect Test for {url} ===")
        
        try:
            # Do not follow redirects
            response = self.session.get(url, allow_redirects=False)
            print(f"Status without redirects: {response.status_code}")
            
            if 300 <= response.status_code < 400:
                location = response.headers.get('Location', 'N/A')
                print(f"Redirect to: {location}")
            
            # Follow redirects
            response = self.session.get(url, allow_redirects=True)
            print(f"Status with redirects: {response.status_code}")
            print(f"Final URL: {response.url}")
            
            # Redirect history
            if hasattr(response.history, '__iter__'):
                print("Redirect History:")
                for i, resp in enumerate(response.history):
                    print(f"  {i+1}. {resp.status_code} -> {resp.url}")
            
        except Exception as e:
            print(f"Redirect Test failed: {e}")
    
    def test_download(self, url, save_path=None):
        """Test file download"""
        print(f"=== Download Test for {url} ===")
        
        try:
            response = self.session.get(url, stream=True)
            
            content_length = int(response.headers.get('content-length', 0))
            print(f"File size: {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
                        
                        # Show progress
                        progress = (downloaded / content_length) * 100 if content_length > 0 else 0
                        print(f"\rDownload: {progress:.1f}%", end="", flush=True)
                
                print(f"\nFile saved: {save_path}")
            
        except Exception as e:
            print(f"Download failed: {e}")
    
    def performance_test(self, url, iterations=10):
        """Performance test"""
        print(f"=== Performance Test for {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} failed: {e}")
        
        if times:
            avg_time = sum(times) / len(times)
            min_time = min(times)
            max_time = max(times)
            
            print(f"\nPerformance Statistics:")
            print(f"  Requests: {len(times)}")
            print(f"  Average: {avg_time:.3f}s")
            print(f"  Minimum: {min_time:.3f}s")
            print(f"  Maximum: {max_time:.3f}s")
            print(f"  Requests/Second: {1/avg_time:.2f}")

# API Client for REST APIs
class APIClient(HTTPClient):
    def __init__(self, base_url):
        super().__init__()
        self.base_url = base_url.rstrip('/')
        
        # API-specific 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 failed: {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 failed: {e}")
            return None

# Main for HTTP demos
def main():
    import sys
    
    # HTTP Client Demo
    client = HTTPClient()
    
    # HTTP methods 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 Model vs TCP/IP Stack

OSI Model (7 Layers)

LayerNameFunctionExamples
7ApplicationApplication protocolsHTTP, FTP, SMTP
6PresentationData conversionSSL/TLS, JPEG
5SessionSession managementNetBIOS, RPC
4TransportEnd-to-End communicationTCP, UDP
3NetworkRouting and addressingIP, ICMP
2Data LinkFrame transmissionEthernet, WiFi
1PhysicalBit transmissionCable, Radio

TCP/IP Stack (4 Layers)

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

Important Port Numbers

Well-Known Ports (0-1023)

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

Registered Ports (1024-49151)

PortProtocolService
3306MySQLDatabase
5432PostgreSQLDatabase
8080HTTP-AltWeb (alternative)
8443HTTPS-AltWeb (alternative)
27017MongoDBNoSQL Database

TCP vs UDP Comparison

PropertyTCPUDP
ConnectionConnection-orientedConnectionless
ReliabilityGuaranteedNot guaranteed
OrderGuaranteedNot guaranteed
Flow ControlYesNo
Error CorrectionYesNo
OverheadHighLow
SpeedSlowerFaster
ApplicationWeb, E-MailStreaming, Gaming

HTTP Status Codes Overview

1xx Informational

  • 100 Continue: Continue
  • 101 Switching Protocols: Protocol switch

2xx Success

  • 200 OK: Successful
  • 201 Created: Created
  • 204 No Content: No content

3xx Redirection

  • 301 Moved Permanently: Permanently moved
  • 302 Found: Temporarily moved
  • 304 Not Modified: Not modified

4xx Client Error

  • 400 Bad Request: Invalid request
  • 401 Unauthorized: Not authorized
  • 403 Forbidden: Forbidden
  • 404 Not Found: Not found
  • 429 Too Many Requests: Too many requests

5xx Server Error

  • 500 Internal Server Error: Internal server error
  • 502 Bad Gateway: Gateway error
  • 503 Service Unavailable: Service unavailable

DNS Record Types

TypeDescriptionExample
AIPv4 addressexample.com → 93.184.216.34
AAAAIPv6 addressexample.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 Programming Basics

TCP Socket Lifecycle

// Server
1. Create ServerSocket
2. Wait for connection (accept)
3. Create InputStream/OutputStream
4. Exchange data
5. Close connection

// Client
1. Create Socket
2. Connect to server
3. Create InputStream/OutputStream
4. Exchange data
5. Close connection

UDP Socket Lifecycle

// Server
1. Create DatagramSocket
2. Wait for packets (receive)
3. Process packet
4. Send response (send)

// Client
1. Create DatagramSocket
2. Send packet (send)
3. Wait for response (receive)
4. Close socket

Advantages and Disadvantages

Advantages of Network Protocols

  • Standardization: Interoperability between systems
  • Scalability: Support for large networks
  • Reliability: Error handling and recovery
  • Flexibility: Different protocols for different purposes

Disadvantages

  • Complexity: Many layers and protocols
  • Overhead: Additional data for protocol information
  • Security: Attack surface for hackers
  • Performance: Network latencies

Common Exam Questions

  1. What is the difference between TCP and UDP? TCP is connection-oriented and reliable, UDP is connectionless and fast but unreliable.

  2. Explain the OSI model! The OSI model describes 7 layers for network communication from Physical to Application.

  3. What is DNS and how does it work? DNS translates domain names into IP addresses and vice versa via hierarchical name servers.

  4. When do you use HTTP vs HTTPS? HTTP for unencrypted communication, HTTPS for encrypted communication with SSL/TLS.

Most Important Sources

  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)
Back to Blog
Share: