- .1. La Abstracción de Sockets y la Capa de Transporte
- Definición de Socket: Un Socket (o punto final de comunicación / endpoint) es una abstracción de software del sistema operativo que actúa como una interfaz de Entrada/Salida (E/S) a través de la cual los procesos pueden enviar y recibir datos en una red de computadoras
- .
- Identificación del Endpoint: Un socket se identifica unívocamente en la red mediante una tupla de 5 elementos (conocida como 5-tuple)
- :
- Puertos: Los sockets utilizan puertos para direccionar los procesos . Los puertos bien conocidos (Well-known Ports) van del 0 al 1023 (por ejemplo, HTTP en el puerto 80, HTTPS en el 443 o SSH en el 22)
- .
2. Comparativa Teórica: Sockets TCP vs. Sockets UDP
La API de sockets estándar ofrece dos abstracciones principales según el comportamiento y los protocolos requeridos en la capa de transporte:
┌──────────────────────────────────────────┐
│ SOCKETS EN LA CAPA DE TRANSPORTE │
└────────────────────┬─────────────────────┘
│
┌─────────────────────────────┴─────────────────────────────┐
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ SOCKETS TCP │ │ SOCKETS UDP │
│ (Stream-Oriented) │ │ (Datagram-Oriented) │
├───────────────────────────┤ ├───────────────────────────┤
│ • Orientado a Conexión │ │ • Sin Conexión (Connectionless)
│ • Flujo de Bytes Continuo │ │ • Conserva Límites (Datagrama)
│ • Control de Flujo/Congestión │ • Sin Garantía de Entrega │
│ • Fiabilidad (ACKs/Retrans) │ • Mínima Sobrecarga (Low Latency)
└───────────────────────────┘ └───────────────────────────┘
A. Sockets TCP (java.net.Socket / java.net.ServerSocket)
- Orientación a conexión: Antes de transmitir datos, los sockets cliente y servidor deben ejecutar una negociación de 3 vías (Three-way Handshake: SYN, SYN-ACK, ACK) para establecer la conexión
- .
B. Sockets UDP (java.net.DatagramSocket / java.net.DatagramPacket)
- Sin Conexión (Connectionless): No requiere negociación ni establecimiento de enlace previo
- .
3. Flujo de Interacción de Sockets
Diagrama de Sockets UDP (Sin Conexión)
Los procesos emisor y receptor interactúan de manera directa enviando paquetes aislados mediante sockets UDP
:
PROCESO SERVIDOR PROCESO CLIENTE
┌──────────────────────┐ ┌──────────────────────┐
│ socket() (Crear) │ │ socket() (Crear) │
└──────────┬───────────┘ └──────────┬───────────┘
│ │
┌──────────▼───────────┐ ┌──────────▼───────────┐
│ bind() (Enlazar │ │ bind() (Puerto │
│ Puerto Conocido) │ │ Efémero / Opcional) │
└──────────┬───────────┘ └──────────┬───────────┘
│ │
┌──────────▼───────────┐ Mensaje en Red ┌──────────▼───────────┐
│ recvfrom() (Espera │ <───────────────────────── │ sendto() (Envía │
│ Datagrama) │ │ Datagrama) │
└──────────┬───────────┘ └──────────┬───────────┘
│ │
│ Mensaje en Red │
│ ─────────────────────────────────────────> │
┌──────────▼───────────┐ ┌──────────▼───────────┐
│ sendto() (Responde) │ │ recvfrom() (Espera │
└──────────┬───────────┘ │ Respuesta) │
│ └──────────┬───────────┘
┌──────────▼───────────┐ ┌──────────▼───────────┐
│ close() (Cerrar) │ │ close() (Cerrar) │
└──────────────────────┘ └──────────────────────┘
Diagrama de Sockets TCP (Orientado a Conexión Multi-hilo)
En TCP, el servidor debe gestionar el establecimiento de la conexión y delegar la atención del cliente para no bloquear el puerto principal
:
PROCESO SERVIDOR PROCESO CLIENTE
┌──────────────────────┐ ┌──────────────────────┐
│ ServerSocket(Puerto) │ │ Socket(IP, Puerto) │
└──────────┬───────────┘ └──────────┬───────────┘
│ │
┌──────────▼───────────┐ Handshake TCP ┌──────────▼───────────┐
│ accept() (Bloqueante)│ <─────────────────────────>│ connect() (Inicia │
└──────────┬───────────┘ (SYN -> SYN-ACK -> ACK) │ Conexión) │
│ └──────────┬───────────┘
┌──────────▼───────────┐ │
│ Genera SocketCliente │ │
│ Dedicado │ │
└──────────┬───────────┘ │
│ │
┌──────────▼───────────┐ Canal TCP de Bytes ┌──────────▼───────────┐
│ Crea Hilo Hijo │ <────────────────────────> │ InputStream / │
│ (ManejadorCliente) │ (InputStream/OutputStream) │ OutputStream │
└──────────────────────┘ └──────────┬───────────┘
│ │
┌──────────▼───────────┐ ┌──────────▼───────────┐
│ Retorna a accept() │ │ close() │
│ para nuevo cliente │ └──────────────────────┘
└──────────────────────┘
4. Concurrencia y Servidores Multihilo
- El método accept() en un ServerSocket TCP es una operación bloqueante por definición
main) debe limitarse estrictamente a escuchar y aceptar conexiones activas en un bucle continuo (while(true))accept() retorna un nuevo objeto Socket exclusivo para el cliente entrante, el servidor delega la tarea instanciando un hilo de ejecución independiente (usando un nuevo Thread con un Runnable o un pool de hilos de tipo ExecutorService)accept()En un programa o sistema distribuido, la decisión de usar TCP o UDP se define en dos niveles distintos: a nivel de código (en la implementación de la API de red) y a nivel de diseño arquitectónico.
1. ¿Dónde se define en el Código? (Nivel de Implementación en Java)
En tu código, se define explícitamente en el momento en que instancias y utilizas las clases de la API de red (
java.net): A. Si eliges TCP (Orientado a Conexión y Streams):
Defines el uso de TCP al importar
java.net.* e instanciar las clases específicas para flujos continuos (streams): - En el Servidor: Instancias
ServerSocket. - En el Cliente: Instancias
Socket. - Intercambio: Utilizas flujos de entrada y salida (
InputStreamyOutputStream/BufferedReaderyPrintWriter) para enviar/recibir datos.
Java
// AL INSTANCIAR ServerSocket / Socket DEFINES QUE USAS TCP
ServerSocket servidor = new ServerSocket(5000); //
Socket socketCliente = servidor.accept(); //
B. Si eliges UDP (Sin Conexión y Datagramas):
Defines el uso de UDP al instanciar las clases específicas para paquetes independientes (datagramas):
- Tanto en Cliente como Servidor: Instancias
DatagramSocket. - Intercambio: Empaquetas los bytes de datos junto a la IP y puerto de destino en objetos
DatagramPacket. - Envío/Recepción: Llamas a los métodos
.send(paquete)y.receive(paquete).
Java
// AL INSTANCIAR DatagramSocket / DatagramPacket DEFINES QUE USAS UDP
DatagramSocket socketUDP = new DatagramSocket(6000); //
DatagramPacket paquete = new DatagramPacket(buffer, buffer.length); //
socketUDP.receive(paquete); //
2. ¿Dónde se define en el Diseño? (Criterio Técnico)
Antes de escribir la primera línea de código, la elección de TCP o UDP la defines según las necesidades de tu aplicación:
| Criterio de Selección | Usas TCP cuando... | Usas UDP cuando... |
| Fiabilidad y Orden | Necesitas garantía de entrega: No te puedes permitir perder ni un solo byte de datos (ej. transferencia de archivos, transacciones, mensajes de chat). | Toleras pérdida ocasional de paquetes: Es más importante que el dato llegue rápido a que llegue completo (ej. streaming de video, voz sobre IP, videojuegos online)[cite: 1]. |
| Sobrecarga (Overhead) | Aceptas la sobrecarga (overhead) del three-way handshake (establecimiento de conexión) y mensajes de confirmación (ACKs)[cite: 1]. | Quieres evitar la sobrecarga de control y minimizar la latencia enviando paquetes directamente[cite: 1]. |
| Control de Flujo | Requieres que la red gestione el control de flujo para no desbordar al receptor[cite: 1]. | Quieres control total del envío de mensajes independientes[cite: 1]. |
3. Casos Especiales en Arquitecturas Distribuidas
- Middleware y RMI / gRPC: Al utilizar librerías de más alto nivel (como Java RMI, gRPC o WebSockets), la librería interna o el framework ya definió por ti el protocolo subyacente (generalmente TCP o HTTP/2 sobre TCP para garantizar que las invocaciones de métodos remotos y serialización de objetos no se pierdan).
- Servidores Híbridos: Tal como se analiza en la materia, un mismo servidor puede soportar múltiples protocolos al mismo tiempo en puertos separados: recibir datos continuos mediante una conexión TCP y recibir alertas o métricas rápidas mediante datagramas UDP en paralelo.
No hay comentarios:
Publicar un comentario