3. TCP (Transmission Control Protocol)

El Transmission Control Protocol (TCP) es el cimiento de casi todo el tráfico confiable de Internet. Establece conversaciones persistentes, numera cada byte y aplica mecanismos que corrigen pérdidas o duplicados sin que la aplicación deba intervenir.

La IETF normalizó el protocolo en documentos como RFC 793 y su actualización RFC 9293, lo que permitió que sistemas operativos muy distintos se entiendan con exactitud bit a bit. Este apartado describe cómo se forma y se mantiene una sesión TCP, cómo se numeran los datos y cómo se reacciona ante cada evento de la red.

3.1 ADN de un protocolo orientado a conexión

TCP combina tres ideas: conexión lógica, control de estado y confiabilidad extremo a extremo. Una conexión lógica significa que ambos extremos acuerdan parámetros antes de enviar datos. El control de estado implica que cada host conoce las transiciones posibles para no mezclar conversaciones. Finalmente, la confiabilidad extremo a extremo se logra numerando bytes, confirmando recepciones y ajustando el ritmo con ventanas deslizantes.

  • Orientado a conexión: no se envía ni un solo byte de aplicación hasta que ambos extremos confirman que existe una sesión.
  • Full duplex: cada lado mantiene contadores independientes para envío y recepción, lo que permite transferencia simultánea en ambas direcciones.
  • Confiable por diseño: la pérdida de un segmento dispara retransmisiones, y los duplicados se desechan gracias a los números de secuencia.
  • Multiplexación: puertos de origen y destino identifican la conversación incluso si varios clientes apuntan al mismo servicio.

Estas características hacen que TCP sea la opción natural para aplicaciones que no pueden tolerar huecos como HTTP, SMTP o SSH, mientras que UDP queda reservado para escenarios donde la velocidad prima sobre la garantía de entrega.

3.2 Establecimiento mediante three-way handshake

El three-way handshake coordina números de secuencia iniciales (ISN) y reserva recursos en ambos equipos antes de transportar datos.

Paso Host Objetivo
1 Cliente Envía SYN con su ISN y anuncia el tamaño inicial de ventana de recepción.
2 Servidor Responde con SYN-ACK: confirma el ISN del cliente (ACK) y publica su propio ISN.
3 Cliente Envía ACK confirmando el ISN del servidor y queda lista la sesión para intercambiar datos.

En una captura de Wireshark se aprecian tres segmentos consecutivos donde el flag SYN aparece primero en uno, luego junto al ACK y finalmente se observa un ACK aislado. Si la red descarta el primer SYN, el cliente reintenta con un temporizador exponencial y puede abandonar la conexión tras superar el número de reintentos configurado.

3.3 Cierre ordenado con four-way handshake

Finalizar una sesión también requiere coordinación. El proceso clásico utiliza cuatro mensajes porque cada dirección de la comunicación se cierra por separado.

  1. El host que deja de enviar datos transmite FIN y pasa al estado FIN-WAIT-1.
  2. El receptor responde con ACK, lo que lleva al emisor a FIN-WAIT-2.
  3. Cuando el receptor está listo para cerrar su flujo, envía FIN.
  4. El primer host contesta con ACK y entra en TIME-WAIT para asegurarse de que no queden segmentos en la red.

TIME-WAIT dura al menos dos veces el RTT estimado, evitando que una nueva conexión reutilice puertos que podrían recibir segmentos rezagados. Ante un problema grave, cualquiera de los extremos puede enviar RST para abortar inmediatamente la sesión, sacrificando la posibilidad de retransmisión controlada.

3.4 Numeración de secuencias y acuses de recibo

Cada byte transmitido por TCP recibe un número dentro de un espacio de 32 bits. El ISN es aleatorio para evitar ataques de predicción. El campo ACK indica el próximo número que el receptor espera, por lo que implícitamente confirma todo lo anterior. Si el emisor envía 100 bytes y recibe un ACK con valor ISN+101 significa que todo llegó y puede liberar memoria.

Cuando llegan datos fuera de orden, el receptor puede almacenar los segmentos y reenviar ACK duplicados para avisar qué byte falta. Al recibir tres ACK duplicados, el emisor ejecuta fast retransmit y vuelve a mandar el segmento ausente sin esperar al temporizador general.

Simulación de numeración y ventana en Python

Este script corta un mensaje en segmentos, simula ACK duplicados y muestra cómo se mueve la ventana de envío:

from collections import deque

def segmentar(mensaje, tamano):
    for inicio in range(0, len(mensaje), tamano):
        yield inicio, mensaje[inicio:inicio + tamano]

def simular_tcp(mensaje, tam_segmento=12, ventana=3):
    pendientes = deque(segmentar(mensaje, tam_segmento))
    enviados = []
    numero_base = 1

    while pendientes or enviados:
        while len(enviados) < ventana and pendientes:
            numero, datos = pendientes.popleft()
            print(f"ENVIO SEQ={numero_base + numero}: {datos!r}")
            enviados.append((numero_base + numero, datos))
        if enviados:
            seq, datos = enviados.pop(0)
            if "perdida" in datos:
                print(f"ACK duplicado por falta del SEQ {seq}")
                enviados.insert(0, (seq, datos))
            else:
                numero_base = seq + len(datos)
                print(f"ACK {numero_base} recibido, ventana avanza")

texto = "TCP reenvia datos cuando detecta perdida y ajusta la ventana"
simular_tcp(texto)

La consola muestra cómo los ACK devuelven espacio en la ventana y cómo un segmento perdido queda al frente hasta que se confirma.

3.5 Retransmisiones y control de temporizadores

Los temporizadores de TCP aseguran que una pérdida no se vuelva permanente. El más conocido es el RTO (Retransmission Timeout), calculado a partir del RTT suavizado (SRTT) y su variación (RTTVAR). El algoritmo de Jacobson/Karels ajusta estos valores de manera dinámica.

  • RTO: si expira antes de recibir ACK la conexión retransmite el segmento inicial y duplica el RTO hasta un límite.
  • Temporizador de persistencia: evita bloqueos cuando la ventana anunciada es cero, enviando probes periódicos.
  • Keepalive (opcional): permite detectar pares inaccesibles en sesiones largas sin tráfico.
  • Delayed ACK: reduce el número de confirmaciones enviando una respuesta conjunta a varios segmentos o a un flujo bidireccional.

Estos temporizadores coordinan el reenvío de paquetes perdidos y mantienen la sesión viva incluso en enlaces de alta latencia. Una mala configuración puede sobrecargar la red si el RTO es demasiado corto o volver la conexión lenta si es exageradamente largo.

3.6 Segmentación y campos del encabezado TCP

Cada segmento contiene una cabecera fija de 20 bytes y una sección opcional con características como escalado de ventana o timestamps. Los campos principales son los siguientes:

Campo Propósito
Puerto origen / destino Identifican proceso emisor y receptor.
Número de secuencia Marca el primer byte de los datos contenidos en el segmento.
Número de ACK Indica el siguiente byte esperado.
Data offset Señala el inicio de los datos e informa el tamaño de opciones.
Flags Controlan el estado de la sesión (SYN, ACK, FIN, RST, PSH, URG, ECE, CWR).
Tamaño de ventana Mide cuántos bytes adicionales puede recibir el host.
Checksum Valida que ni la cabecera ni los datos llegaran corruptos.
Puntero urgente Identifica información marcada como urgente cuando URG está activo.
Opciones Permiten negociar MSS, timestamps, SACK o escalado de ventana.

Gracias a la segmentación, cada flujo puede adaptarse al MTU del enlace sin desperdiciar ancho de banda ni forzar fragmentación en capas inferiores.

3.7 Flags más utilizados

Los flags ocupan un solo byte pero definen la mitad de la lógica de TCP. Su combinación describe eventos como apertura, cierre o prioridad.

Flag Descripción
SYN Solicita apertura de sesión y transporta el ISN.
ACK Confirma recepciones. Está presente en casi todos los segmentos posteriores al handshake.
FIN Inicia un cierre ordenado de una dirección del canal.
RST Aborta la sesión de inmediato ante errores graves o puertos no escuchando.
PSH Indica que los datos deben entregarse enseguida a la aplicación, sin esperar a llenar buffers.
URG Marca datos urgentes y habilita el puntero correspondiente.
ECE / CWR Soportan congestion notification explícita, permitiendo reaccionar antes de perder paquetes.

Tanto PSH como URG se usan menos en aplicaciones modernas, pero resultan útiles en protocolos interactivos que priorizan la latencia.

3.8 Observación práctica en herramientas

Capturar un flujo HTTP revela en segundos los conceptos teóricos. Al iniciar la captura se ve el three-way handshake, luego un estallido de segmentos con PSH cuando se intercambian encabezados y finalmente un four-way handshake al cerrar la sesión. Activar la columna “Bytes in flight” en Wireshark permite estimar la ventana efectiva.

Cuando se producen pérdidas, Wireshark marca los retransmissions y los Fast Retransmissions en rojo o naranja. Comparar los RTT de cada segmento ayuda a detectar enlaces saturados o firewalls que agregan latencia.

3.9 Diagnóstico rápido con PowerShell

Windows expone comandos que permiten comprobar si un puerto TCP responde sin instalar herramientas adicionales.

Comandos útiles

Test-NetConnection -ComputerName www.example.com -Port 443 -InformationLevel Detailed
Get-NetTCPConnection -State Established | Select-Object -First 5

Test-NetConnection realiza el three-way handshake y devuelve el RTT estimado, el estado del puerto y la dirección IP resuelta. Get-NetTCPConnection lista las sesiones activas con sus puertos, lo que facilita detectar conexiones huérfanas o el abuso de puertos efímeros.

3.10 Cierre del tema

TCP es mucho más que un contenedor de bytes: es una máquina de estados cuidadosamente diseñada para convivir con redes imperfectas. Su three-way handshake, la numeración de secuencias y los temporizadores de retransmisión proporcionan la confiabilidad que innumerables aplicaciones necesitan. En el siguiente tema se analizará cómo los puertos TCP permiten identificar servicios específicos dentro de un mismo host y habilitan la multiplexación masiva de conexiones.