Skip to content
IRC-CodingIRC-Coding
Protocolos de redTCP UDP IPDNS HTTP HTTPSModelo OSITCP IP Stack

Protocolos de Red: TCP, UDP, IP, DNS, HTTP/HTTPS

Fundamentos de protocolos de red: TCP, UDP, IP, DNS, HTTP/HTTPS. Modelos OSI y TCP/IP con ejemplos prácticos.

S

schutzgeist

26 min read
Protocolos de Red: TCP, UDP, IP, DNS, HTTP/HTTPS

Protocolos de red: TCP, UDP, IP, DNS, HTTP/HTTPS y modelos OSI/TCP-IP

Este artículo es una introducción completa a los protocolos de red, incluyendo TCP, UDP, IP, DNS, HTTP/HTTPS, el modelo OSI y la pila TCP/IP con ejemplos prácticos.

En resumen

Los protocolos de red regulan la comunicación entre computadoras. TCP/IP es la pila de protocolos fundamental, OSI describe 7 capas, HTTP/HTTPS permiten la comunicación web y DNS resuelve nombres en direcciones IP.

Descripción técnica compacta

Los protocolos de red son reglas y convenciones estandarizadas para la comunicación de datos entre computadoras en una red.

Protocolos importantes:

TCP (Transmission Control Protocol)

  • Tipo: Orientado a conexión, confiable
  • Características: Handshake de tres vías, control de flujo, corrección de errores
  • Aplicación: Web, correo electrónico, transferencia de archivos
  • Puerto: 80 (HTTP), 443 (HTTPS), 25 (SMTP)

UDP (User Datagram Protocol)

  • Tipo: Sin conexión, no confiable
  • Características: Simple, rápido, sin garantías
  • Aplicación: Streaming, juegos, DNS
  • Puerto: 53 (DNS), 123 (NTP), 67 (DHCP)

IP (Internet Protocol)

  • Tipo: Conmutación de paquetes, enrutamiento
  • Versiones: IPv4 (32 bits), IPv6 (128 bits)
  • Características: Direccionamiento, fragmentación
  • Aplicación: Base de Internet

DNS (Domain Name System)

  • Tipo: Resolución de nombres
  • Función: Dominio → dirección IP
  • Tipos de registro: A, AAAA, MX, NS, CNAME
  • Puerto: 53 (UDP/TCP)

HTTP/HTTPS (Hypertext Transfer Protocol)

  • Tipo: Protocolo de aplicación para web
  • Métodos: GET, POST, PUT, DELETE
  • Estados: 200 OK, 404 Not Found, 500 Server Error
  • Puerto: 80 (HTTP), 443 (HTTPS)

Puntos relevantes para exámenes

Estos puntos son la columna vertebral de los exámenes para técnicos en informática (IHK AP1/AP2). En la prueba no solo debes mencionar términos, sino explicar diferencias, asignar casos de uso y establecer conexiones.

  • Protocolos de red: Reglas para la comunicación basada en computadoras. Explicación: Sin protocolos estandarizados, los sistemas diferentes no podrían comunicarse entre sí. Regulan el formato, el orden, el manejo de errores y la confirmación.
  • TCP: Orientado a conexión, confiable, handshake de tres vías (SYN → SYN-ACK → ACK). Explicación: TCP garantiza la transferencia completa y correcta de datos. En el examen debes explicar el handshake y saber cuándo se utiliza TCP (web, correo electrónico, FTP).
  • UDP: Sin conexión, rápido, no confiable. Explicación: UDP envía sin establecer una conexión y sin confirmación de recepción. En el examen debes destacar el contraste con TCP y nombrar aplicaciones donde la velocidad es más importante (DNS, VoIP, juegos, streaming).
  • IP: Conmutación de paquetes, enrutamiento, IPv4 (32 bits) frente a IPv6 (128 bits). Explicación: IP es el fundamento de Internet. Debes explicar la diferencia entre IPv4 (direcciones limitadas, NAT necesario) e IPv6 (direcciones ilimitadas) y entender cómo los routers reenvían paquetes.
  • DNS: Resolución de nombres, dominio → dirección IP. Explicación: DNS traduce nombres legibles para humanos en direcciones de máquina. En el examen debes explicar la estructura jerárquica (raíz → TLD → autoritativo) y los tipos de registro (A, AAAA, MX, CNAME).
  • HTTP/HTTPS: Comunicación web, solicitud/respuesta. Explicación: Debes explicar los métodos (GET, POST, PUT, DELETE) y códigos de estado (200, 404, 500) y destacar la diferencia entre HTTP (puerto 80, sin cifrar) y HTTPS (puerto 443, TLS).
  • Modelo OSI: Modelo de 7 capas. Explicación: En el examen debes nombrar las capas y asignarlas: Capa 2 = Data Link (Switch), Capa 3 = Network (Router, IP), Capa 4 = Transport (TCP, UDP), Capa 7 = Application (HTTP, DNS).
  • Pila TCP/IP: Modelo de 4 capas. Explicación: TCP/IP es el modelo utilizado prácticamente en Internet. Debes poder asignar las 4 capas a las 7 capas OSI (por ejemplo, Application de TCP/IP = capas 5-7 de OSI).
  • Relevancia para IHK: Base para la administración y el desarrollo de redes. Explicación: En AP1 y AP2 se prueban regularmente redes, protocolos y seguridad. El aprendizaje repetido lleva a momentos de iluminación.

Componentes centrales

Los componentes centrales forman el fundamento técnico de la comunicación en red. Quien entienda estas piezas no solo puede describir protocolos, sino también analizar problemas de red y desarrollar sus propias aplicaciones de red.

  1. Modelo OSI: Modelo teórico de 7 capas. Por qué es importante: El modelo OSI proporciona un lenguaje común para describir la comunicación de red. Cuando un colega dice “El problema está en la capa 3”, sabes inmediatamente que el enrutamiento/IP está afectado. Te ayuda a delimitar errores de forma sistemática.
  2. Pila TCP/IP: Modelo práctico de 4 capas. Por qué es importante: TCP/IP es el modelo realmente utilizado en Internet. Es más compacto que OSI e inmediatamente implementable. Si entiendes TCP/IP, entiendes cómo funciona realmente Internet.
  3. Protocolos de transporte: TCP, UDP para transporte de datos. Por qué es importante: La elección del protocolo de transporte determina qué tan confiable es la comunicación de tu aplicación. Una app de banca necesita TCP, un stream en vivo necesita UDP. Tú como desarrollador tomas esta decisión activamente.
  4. Protocolos de red: IP para enrutamiento y direccionamiento. Por qué es importante: Las direcciones IP son como direcciones postales en la red. Sin direccionamiento correcto, los datos no llegan. IPv4 frente a IPv6 es un tema de migración actual en muchas empresas.
  5. Protocolos de aplicación: HTTP, DNS, SMTP para servicios. Por qué es importante: Estos protocolos son la interfaz entre el usuario y la red. Cada acceso a un sitio web utiliza HTTP, cada nombre de dominio necesita DNS. Como desarrollador, trabajas con ellos diariamente.
  6. Números de puerto: Identificación de servicios. Por qué es importante: Una dirección IP por sí sola no es suficiente. En un servidor a menudo se ejecutan varios servicios simultáneamente. Los puertos (por ejemplo, 80 para HTTP, 443 para HTTPS) dirigen el tráfico al programa correcto. En el examen debes conocer los puertos bien conocidos.
  7. Programación de sockets: Comunicación de red. Por qué es importante: Los sockets son la interfaz de programación para redes. Quien entienda sockets puede construir sus propios servidores y clientes. Eso distingue a un desarrollador de aplicaciones de un simple usuario.
  8. Seguridad de red: Firewalls, VPN, TLS. Por qué es importante: Cada red abierta es un objetivo de ataque. TLS cifra datos, los firewalls bloquean tráfico no deseado. En el examen y en la práctica, la seguridad no es un complemento opcional, sino un requisito.

Ejemplos prácticos

1. Programación de sockets TCP con Java

¿Qué hace este código? Este programa Java muestra un servidor TCP completo con gestión de pool de threads, capaz de atender múltiples clientes simultáneamente. También incluye un cliente TCP y pruebas de rendimiento para latencia y throughput.

¿Por qué es útil entenderlo? TCP es el protocolo de transporte más utilizado en Internet. Quien entienda cómo se construye un servidor TCP, también entiende cómo funcionan fundamentalmente los servidores web, servidores de correo y bases de datos. El handshake de tres vías, la gestión de conexiones y el manejo de threads son conceptos centrales en el examen y en la práctica.

¿Qué puedes aprender de esto?

  • Cómo un ServerSocket acepta conexiones y las delega a threads separados
  • Cómo intercambiar datos bidireccionales con BufferedReader y PrintWriter
  • Por qué un pool de threads es importante para no crear miles de threads
  • Cómo medir latencia y throughput de forma programática
  • Cómo cerrar correctamente las conexiones de cliente y liberar recursos

Si no dominas Java o no lo has aprendido, lee este ejemplo de todas formas. Pero presta más atención a la estructura. Cuándo se asignan las variables globales, cuándo la conexión real del cliente, cuándo aparecen las instrucciones try y por qué exactamente ahí… Más abajo encontrarás otro ejemplo en Python.

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. Programación de sockets UDP con Python

¿Qué hace este código? Este programa Python muestra un servidor UDP con función de broadcast, un cliente UDP interactivo, pruebas de rendimiento para latencia, throughput y pérdida de paquetes, además de una demostración de UDP Multicast.

¿Por qué es importante entenderlo? UDP es lo opuesto a TCP: rápido pero poco confiable. Quien entiende UDP sabe cuándo la velocidad es más importante que la confiabilidad. Broadcasting y Multicast son conceptos fundamentales para descubrimiento de redes, streaming y comunicación IoT. En los exámenes deberás poder contrastar TCP y UDP.

¿Qué puedes aprender?

  • Cómo crear sockets UDP con socket.SOCK_DGRAM
  • Por qué UDP no requiere establecimiento de conexión y cómo recvfrom entrega las direcciones del remitente
  • Cómo funciona el broadcasting hacia todos los clientes y el multicast hacia un grupo
  • Por qué UDP tiene pérdida de paquetes y cómo medirlo
  • Cómo usar threads para enviar y recibir simultáneamente

Presta especial atención a la estructura del ejemplo. Analiza los imports desde el inicio y pregúntate por qué se importan y podrían ser necesarios.

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):
        """Inicio del servidor UDP"""
        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:
                # Recibir datos
                data, client_address = self.server_socket.recvfrom(2048)
                
                # Agregar cliente a la lista
                self.clients.add(client_address)
                
                print(f"Mensaje de {client_address}: {data.decode()}")
                
                # Enviar mensaje a todos los clientes (broadcast)
                self.broadcast(data, client_address)
                
            except Exception as e:
                print(f"Error al recibir: {e}")
    
    def broadcast(self, message, sender_address):
        """Enviar mensaje a todos los clientes"""
        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 al enviar a {client}: {e}")
    
    def stop(self):
        """Detener servidor"""
        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):
        """Inicio del cliente UDP"""
        self.running = True
        print(f"UDP Client connected to {self.host}:{self.port}")
        
        # Iniciar thread de recepción
        receive_thread = threading.Thread(target=self.receive_messages)
        receive_thread.daemon = True
        receive_thread.start()
        
        try:
            while self.running:
                # Ingresar mensaje
                message = input(f"{username}: ")
                
                if message.lower() == 'exit':
                    break
                
                # Enviar mensaje
                full_message = f"{username}: {message}"
                self.client_socket.sendto(full_message.encode(), (self.host, self.port))
                
        except KeyboardInterrupt:
            print("\nCliente terminado")
        finally:
            self.stop()
    
    def receive_messages(self):
        """Recibir mensajes del servidor"""
        while self.running:
            try:
                data, server = self.client_socket.recvfrom(2048)
                print(f"\r{data.decode()}")
                print("Mensaje: ", end="", flush=True)
                
            except Exception as e:
                if self.running:
                    print(f"Error al recibir: {e}")
                break
    
    def stop(self):
        """Detener cliente"""
        self.running = False
        self.client_socket.close()
        print("UDP Client stopped")

# Prueba de rendimiento UDP
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):
        """Prueba de latencia UDP"""
        print(f"=== UDP Latency Test ===")
        
        latencies = []
        
        for i in range(iterations):
            start_time = time.time()
            
            # Enviar mensaje ping
            self.socket.sendto(b"ping", (self.host, self.port))
            
            # Recibir respuesta
            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 en ping {i+1}")
        
        if latencies:
            avg_latency = sum(latencies) / len(latencies)
            min_latency = min(latencies)
            max_latency = max(latencies)
            
            print(f"\nEstadísticas de latencia:")
            print(f"  Promedio: {avg_latency:.2f}ms")
            print(f"  Mínimo: {min_latency:.2f}ms")
            print(f"  Máximo: {max_latency:.2f}ms")
    
    def test_throughput(self, data_size=1024, duration=5):
        """Prueba de throughput UDP"""
        print(f"\n=== UDP Throughput Test ===")
        
        # Crear datos de prueba
        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 += 1
                
                # Pausa breve para no saturar el servidor
                time.sleep(0.001)
                
            except Exception as e:
                print(f"Error al enviar: {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"Estadísticas de throughput:")
        print(f"  Paquetes enviados: {packets_sent}")
        print(f"  Duración total: {total_time:.2f}s")
        print(f"  Paquetes/segundo: {packets_per_second:.2f}")
        print(f"  Throughput: {throughput:.2f} KB/s")
    
    def test_packet_loss(self, packets=1000):
        """Prueba de pérdida de paquetes UDP"""
        print(f"\n=== UDP Packet Loss Test ===")
        
        packets_lost = 0
        
        for i in range(packets):
            try:
                # Enviar número secuencial
                packet = f"packet_{i}".encode()
                self.socket.sendto(packet, (self.host, self.port))
                
                # Pausa breve
                time.sleep(0.001)
                
            except Exception as e:
                packets_lost += 1
        
        loss_rate = (packets_lost / packets) * 100
        print(f"Estadísticas de pérdida de paquetes:")
        print(f"  Paquetes enviados: {packets}")
        print(f"  Paquetes perdidos: {packets_lost}")
        print(f"  Tasa de pérdida: {loss_rate:.2f}%")
    
    def close(self):
        """Cerrar socket"""
        self.socket.close()

# Demostración de UDP Multicast
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):
        """Crear emisor multicast"""
        sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # Configurar TTL (cuántos hops puede hacer el paquete)
        ttl = struct.pack('b', 1)
        sender.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
        
        return sender
    
    def create_multicast_receiver(self):
        """Crear receptor multicast"""
        receiver = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # Vincular socket a la dirección multicast
        receiver.bind(('', self.port))
        
        # Unirse al grupo multicast
        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):
        """Enviar mensaje multicast"""
        sender = self.create_multicast_sender()
        
        try:
            sender.sendto(message.encode(), (self.multicast_group, self.port))
            print(f"Multicast enviado: {message}")
        finally:
            sender.close()
    
    def receive_multicast(self):
        """Recibir mensajes multicast"""
        receiver = self.create_multicast_receiver()
        
        try:
            print(f"Receptor multicast escuchando en {self.multicast_group}:{self.port}")
            
            while True:
                try:
                    data, address = receiver.recvfrom(1024)
                    print(f"Multicast desde {address}: {data.decode()}")
                    
                except KeyboardInterrupt:
                    break
                    
        finally:
            # Salir del grupo
            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 para demostraciones UDP
def main():
    import sys
    
    if len(sys.argv) > 1:
        mode = sys.argv[1]
        
        if mode == "server":
            # Iniciar servidor UDP
            server = UDPServer()
            try:
                server.start()
            except KeyboardInterrupt:
                server.stop()
                
        elif mode == "client":
            # Iniciar cliente UDP
            username = input("Su nombre: ")
            client = UDPClient()
            client.start(username)
            
        elif mode == "performance":
            # Pruebas de rendimiento
            test = UDPPerformanceTest()
            test.test_latency(100)
            test.test_throughput(1024, 5)
            test.test_packet_loss(1000)
            test.close()
            
        elif mode == "multicast_send":
            # Emisor multicast
            multicast = UDPMulticastDemo()
            while True:
                message = input("Mensaje multicast (o 'exit'): ")
                if message.lower() == 'exit':
                    break
                multicast.send_multicast(message)
                
        elif mode == "multicast_receive":
            # Receptor multicast
            multicast = UDPMulticastDemo()
            multicast.receive_multicast()
            
        else:
            print("Uso: python udp_demo.py [server|client|performance|multicast_send|multicast_receive]")
    else:
        print("Uso: python udp_demo.py [server|client|performance|multicast_send|multicast_receive]")

if __name__ == "__main__":
    main()

3. Consultas DNS con diferentes lenguajes de programación

¿Qué hace este código? Este programa Java muestra varios tipos de búsquedas DNS: resolución normal de nombres (dominio → IP), DNS inverso (IP → dominio), consulta de todas las direcciones IP, pruebas de rendimiento DNS y una comparación de caché DNS (primera búsqueda versus segunda).

¿Por qué es útil entender esto? DNS es la guía telefónica de Internet. Sin DNS tendrías que memorizar direcciones IP. En exámenes y en el trabajo diario necesitas diagnosticar problemas DNS, ya sea un A-Record incorrecto, un caché expirado o un servidor de nombres inaccesible. Cuando entiendes DNS, entiendes por qué algunos sitios web funcionan y otros no.

¿Qué puedes aprender?

  • Cómo InetAddress.getByName() traduce nombres de dominio en IPs
  • Cómo funciona DNS inverso con la misma clase
  • Por qué el caché DNS es importante y cómo afecta el rendimiento
  • Cómo evaluar comparativamente búsquedas DNS de forma programática
  • La diferencia entre IPv4 (Inet4Address) e IPv6 (Inet6Address)
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. Cliente HTTP/HTTPS con características avanzadas

¿Qué hace este código? Este programa Python implementa un cliente HTTP/HTTPS completo con características avanzadas: estrategia de reintentos, diversos métodos HTTP (GET, POST, HEAD, OPTIONS), verificación de certificados SSL/TLS, gestión de cookies, seguimiento de redirecciones, descarga de archivos con indicador de progreso, pruebas de rendimiento y un cliente API para endpoints REST.

¿Por qué vale la pena entenderlo? HTTP/HTTPS es el protocolo de aplicación más importante en la web. Cada llamada a una API, cada visita a una página web y cada sincronización de datos utiliza HTTP. Quien entienda cómo funcionan las peticiones, respuestas, códigos de estado, encabezados y sesiones podrá depurar APIs, identificar problemas de seguridad y construir aplicaciones web de alto rendimiento. En los exámenes, los métodos HTTP y códigos de estado son preguntas estándar.

¿Qué puedes aprender de esto?

  • Cómo construir una conexión reutilizable usando requests.Session()
  • Por qué las estrategias de reintentos importan y cómo implementarlas con urllib3.util.retry
  • Cómo extraer información de certificados SSL y versiones TLS
  • Cómo se transmiten automáticamente las cookies entre peticiones
  • Cómo rastrear o bloquear redirecciones
  • Cómo descargar archivos grandes eficientemente con stream=True
  • Cómo construir un cliente API REST genérico con operaciones CRUD
import requests
import json
import time
import ssl
import urllib3
from urllib3.util.retry import Retry
from datetime import datetime

# HTTP Client con características avanzadas
class HTTPClient:
    def __init__(self):
        self.session = requests.Session()
        self.setup_session()
        
    def setup_session(self):
        """Configurar la sesión"""
        # Estrategia de reintentos
        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 configurado")
    
    def get_request(self, url, params=None):
        """Petición GET con manejo de errores"""
        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 falló: {e}")
            return None
    
    def post_request(self, url, data=None, json_data=None):
        """Petición POST con datos"""
        try:
            print(f"POST Request: {url}")
            
            if json_data:
                print(f"Datos JSON: {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 falló: {e}")
            return None
    
    def print_response_info(self, response, duration):
        """Mostrar información de la respuesta"""
        print(f"Código de estado: {response.status_code}")
        print(f"Tiempo de respuesta: {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')}")
        
        # Mostrar encabezados
        if response.headers:
            print("Encabezados de la respuesta:")
            for key, value in response.headers.items():
                print(f"  {key}: {value}")
    
    def test_http_methods(self, url):
        """Probar diferentes métodos HTTP"""
        print(f"=== Prueba de métodos HTTP para {url} ===")
        
        # GET
        print("\n--- GET ---")
        response = self.get_request(url)
        
        # HEAD
        print("\n--- HEAD ---")
        try:
            response = self.session.head(url)
            print(f"Estado HEAD: {response.status_code}")
            print(f"Encabezados HEAD: {dict(response.headers)}")
        except Exception as e:
            print(f"HEAD Request falló: {e}")
        
        # OPTIONS
        print("\n--- OPTIONS ---")
        try:
            response = self.session.options(url)
            print(f"Estado OPTIONS: {response.status_code}")
            allowed_methods = response.headers.get('Allow', 'N/A')
            print(f"Métodos permitidos: {allowed_methods}")
        except Exception as e:
            print(f"OPTIONS Request falló: {e}")
    
    def test_https_features(self, url):
        """Probar características HTTPS"""
        print(f"=== Prueba de características HTTPS para {url} ===")
        
        try:
            # Información del certificado SSL
            response = self.session.get(url)
            
            # Mostrar información SSL
            cert_info = response.raw._connection.peer.cert
            if cert_info:
                print("Información del certificado SSL:")
                for cert in cert_info:
                    print(f"  Sujeto: {cert.subject}")
                    print(f"  Emisor: {cert.issuer}")
                    print(f"  Válido desde: {cert.not_valid_before}")
                    print(f"  Válido hasta: {cert.not_valid_after}")
                    print(f"  Serie: {cert.serial_number}")
            
            # Versión TLS
            tls_version = response.raw._connection.tls_version
            print(f"Versión TLS: {tls_version}")
            
            # Suite de cifrado
            cipher_suite = response.raw._connection.cipher
            print(f"Suite de cifrado: {cipher_suite}")
            
        except Exception as e:
            print(f"Prueba de características HTTPS falló: {e}")
    
    def test_authentication(self, url, username, password):
        """Probar autenticación HTTP"""
        print(f"=== Prueba de autenticación para {url} ===")
        
        # Autenticación básica
        try:
            from requests.auth import HTTPBasicAuth
            
            auth = HTTPBasicAuth(username, password)
            response = self.session.get(url, auth=auth)
            
            print(f"Estado autenticación básica: {response.status_code}")
            
            if response.status_code == 200:
                print("Autenticación básica exitosa")
            else:
                print("Autenticación básica falló")
                
        except Exception as e:
            print(f"Prueba de autenticación falló: {e}")
    
    def test_cookies(self, url):
        """Probar gestión de cookies"""
        print(f"=== Prueba de cookies para {url} ===")
        
        try:
            # Primera petición sin cookies
            response1 = self.session.get(url)
            print(f"Estado de primera petición: {response1.status_code}")
            print(f"Cookies tras primera petición: {len(self.session.cookies)}")
            
            # Segunda petición con cookies
            response2 = self.session.get(url)
            print(f"Estado de segunda petición: {response2.status_code}")
            print(f"Cookies tras segunda petición: {len(self.session.cookies)}")
            
            # Información de cookies
            if self.session.cookies:
                print("Detalles de cookies:")
                for cookie in self.session.cookies:
                    print(f"  {cookie.name}: {cookie.value}")
                    print(f"    Dominio: {cookie.domain}")
                    print(f"    Ruta: {cookie.path}")
                    print(f"    Seguro: {cookie.secure}")
                    print(f"    Solo HTTP: {cookie.has_attr('HttpOnly')}")
            
        except Exception as e:
            print(f"Prueba de cookies falló: {e}")
    
    def test_redirects(self, url):
        """Probar gestión de redirecciones"""
        print(f"=== Prueba de redirecciones para {url} ===")
        
        try:
            # No seguir redirecciones
            response = self.session.get(url, allow_redirects=False)
            print(f"Estado sin redirecciones: {response.status_code}")
            
            if 300 <= response.status_code < 400:
                location = response.headers.get('Location', 'N/A')
                print(f"Redirigir a: {location}")
            
            # Seguir redirecciones
            response = self.session.get(url, allow_redirects=True)
            print(f"Estado con redirecciones: {response.status_code}")
            print(f"URL final: {response.url}")
            
            # Historial de redirecciones
            if hasattr(response.history, '__iter__'):
                print("Historial de redirecciones:")
                for i, resp in enumerate(response.history):
                    print(f"  {i+1}. {resp.status_code} -> {resp.url}")
            
        except Exception as e:
            print(f"Prueba de redirecciones falló: {e}")
    
    def test_download(self, url, save_path=None):
        """Probar descarga de archivos"""
        print(f"=== Prueba de descarga para {url} ===")
        
        try:
            response = self.session.get(url, stream=True)
            
            content_length = int(response.headers.get('content-length', 0))
            print(f"Tamaño del archivo: {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
                        
                        # Mostrar progreso
                        progress = (downloaded / content_length) * 100 if content_length > 0 else 0
                        print(f"\rDescarga: {progress:.1f}%", end="", flush=True)
                
                print(f"\nArchivo guardado: {save_path}")
            
        except Exception as e:
            print(f"Descarga falló: {e}")
    
    def performance_test(self, url, iterations=10):
        """Prueba de rendimiento"""
        print(f"=== Prueba de rendimiento para {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"Petición {i+1}: {duration:.3f}s")
                
            except Exception as e:
                print(f"Petición {i+1} falló: {e}")
        
        if times:
            avg_time = sum(times) / len(times)
            min_time = min(times)
            max_time = max(times)
            
            print(f"\nEstadísticas de rendimiento:")
            print(f"  Peticiones: {len(times)}")
            print(f"  Promedio: {avg_time:.3f}s")
            print(f"  Mínimo: {min_time:.3f}s")
            print(f"  Máximo: {max_time:.3f}s")
            print(f"  Peticiones/segundo: {1/avg_time:.2f}")

# Cliente API para APIs REST
class APIClient(HTTPClient):
    def __init__(self, base_url):
        super().__init__()
        self.base_url = base_url.rstrip('/')
        
        # Encabezados específicos de API
        self.session.headers.update({
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        })
    
    def get_resource(self, resource, params=None):
        """GET Recurso"""
        url = f"{self.base_url}/{resource.lstrip('/')}"
        return self.get_request(url, params)
    
    def create_resource(self, resource, data):
        """POST Recurso"""
        url = f"{self.base_url}/{resource.lstrip('/')}"
        return self.post_request(url, json_data=data)
    
    def update_resource(self, resource, data):
        """PUT Recurso"""
        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 falló: {e}")
            return None
    
    def delete_resource(self, resource):
        """DELETE Recurso"""
        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 falló: {e}")
            return None

# Main para demostraciones HTTP
def main():
    import sys
    
    # Demo de cliente HTTP
    client = HTTPClient()
    
    # Prueba de métodos HTTP
    client.test_http_methods("https://httpbin.org")
    
    # Prueba de características HTTPS
    client.test_https_features("https://google.com")
    
    # Prueba de redirecciones
    client.test_redirects("http://httpbin.org/redirect/1")
    
    # Prueba de cookies
    client.test_cookies("https://httpbin.org/cookies/set/test/value")
    
    # Prueba de rendimiento
    client.performance_test("https://httpbin.org/get", 20)
    
    # Demo de cliente API
    api_client = APIClient("https://jsonplaceholder.typicode.com")
    
    # GET Users
    users_response = api_client.get_resource("/users")
    if users_response:
        print(f"Usuarios: {users_response.json()}")
    
    # Crear Post
    new_post = {
        "title": "Test Post",
        "body": "Test Body",
        "userId": 1
    }
    create_response = api_client.create_resource("/posts", new_post)
    
    # Prueba de descarga
    client.test_download("https://httpbin.org/bytes/1024", "test_download.bin")

if __name__ == "__main__":
    main()

Modelo OSI vs Pila TCP/IP

Modelo OSI (7 capas)

CapaNombreFunciónEjemplos
7ApplicationProtocolos de aplicaciónHTTP, FTP, SMTP
6PresentationTransformación de datosSSL/TLS, JPEG
5SessionGestión de sesionesNetBIOS, RPC
4TransportComunicación end-to-endTCP, UDP
3NetworkEncaminamiento y direccionamientoIP, ICMP
2Data LinkTransmisión de framesEthernet, WiFi
1PhysicalTransmisión de bitsCables, radio

Pila TCP/IP (4 capas)

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

Números de puerto importantes

Well-Known Ports (0-1023)

PuertoProtocoloServicio
20FTPTransferencia de archivos (datos)
21FTPTransferencia de archivos (control)
22SSHSecure Shell
23TelnetTerminal remota
25SMTPCorreo electrónico
53DNSSistema de nombres de dominio
80HTTPWeb (sin cifrar)
110POP3Correo (Post Office)
143IMAPCorreo (Internet Message)
443HTTPSWeb (cifrado)
993IMAPSIMAP sobre SSL
995POP3SPOP3 sobre SSL

Registered Ports (1024-49151)

PuertoProtocoloServicio
3306MySQLBase de datos
5432PostgreSQLBase de datos
8080HTTP-AltWeb (alternativo)
8443HTTPS-AltWeb (alternativo)
27017MongoDBBase de datos NoSQL

Comparativa TCP vs UDP

CaracterísticaTCPUDP
ConexiónOrientado a conexiónSin conexión
ConfiabilidadGarantizadaNo garantizada
OrdenGarantizadoNo garantizado
Control de flujoNo
Corrección de erroresNo
OverheadAltoBajo
VelocidadMás lentoMás rápido
AplicacionesWeb, correoStreaming, videojuegos

Códigos de estado HTTP

1xx Informativo

  • 100 Continue: Continuar
  • 101 Switching Protocols: Cambio de protocolo

2xx Éxito

  • 200 OK: Exitoso
  • 201 Created: Creado
  • 204 No Content: Sin contenido

3xx Redirección

  • 301 Moved Permanently: Movido permanentemente
  • 302 Found: Encontrado (temporal)
  • 304 Not Modified: No modificado

4xx Error del cliente

  • 400 Bad Request: Solicitud inválida
  • 401 Unauthorized: No autorizado
  • 403 Forbidden: Prohibido
  • 404 Not Found: No encontrado
  • 429 Too Many Requests: Demasiadas solicitudes

5xx Error del servidor

  • 500 Internal Server Error: Error interno del servidor
  • 502 Bad Gateway: Error de puerta de enlace
  • 503 Service Unavailable: Servicio no disponible

Tipos de registros DNS

TipoDescripciónEjemplo
ADirección IPv4example.com → 93.184.216.34
AAAADirección IPv6example.com → 2606:2800:220:1
MXIntercambio de correoexample.com → mail.example.com
NSServidor de nombresexample.com → ns1.example.com
CNAMENombre canónicowww.example.com → example.com
TXTInformación de textoexample.com → “v=spf1 include:_spf.google.com ~all”
PTRPuntero (inverso)93.184.216.34 → example.com

Fundamentos de programación con sockets

Ciclo de vida de un socket TCP

// Servidor
1. Crear ServerSocket
2. Esperar conexión (accept)
3. Crear InputStream/OutputStream
4. Intercambiar datos
5. Cerrar conexión

// Cliente
1. Crear Socket
2. Conectar con servidor
3. Crear InputStream/OutputStream
4. Intercambiar datos
5. Cerrar conexión

Ciclo de vida de un socket UDP

// Servidor
1. Crear DatagramSocket
2. Esperar paquetes (receive)
3. Procesar paquete
4. Enviar respuesta (send)

// Cliente
1. Crear DatagramSocket
2. Enviar paquete (send)
3. Esperar respuesta (receive)
4. Cerrar socket

Ventajas y desventajas

Ventajas de los protocolos de red

  • Estandarización: Interoperabilidad entre sistemas
  • Escalabilidad: Compatibilidad con redes grandes
  • Confiabilidad: Manejo de errores y recuperación
  • Flexibilidad: Diferentes protocolos para diferentes casos de uso

Desventajas

  • Complejidad: Muchas capas y protocolos
  • Overhead: Datos adicionales para información de protocolo
  • Seguridad: Superficies de ataque para hackers
  • Performance: Latencias de red

Preguntas frecuentes de examen

  1. ¿Cuál es la diferencia entre TCP y UDP? TCP es orientado a conexión y confiable, UDP es sin conexión, rápido pero no confiable.

  2. ¡Explica el modelo OSI! El modelo OSI describe 7 capas para comunicación de red, desde Physical hasta Application.

  3. ¿Qué es DNS y cómo funciona? DNS traduce nombres de dominio a direcciones IP y viceversa a través de servidores de nombres jerárquicos.

  4. ¿Cuándo se usa HTTP vs HTTPS? HTTP para comunicación sin cifrar, HTTPS para comunicación cifrada con SSL/TLS.

Fuentes principales

  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)
Volver al blog
Share:

Entradas relacionadas