El control de flujo impide que un emisor rápido desborde la memoria del receptor. TCP logra este equilibrio mediante ventanas deslizantes que crecen o se contraen según la capacidad real de ambos extremos.
A diferencia del control de congestión, que observa el estado de la red, el control de flujo se concentra en el host destino. Su objetivo es sencillo: entregar datos al ritmo que la aplicación receptora puede procesarlos, sin sacrificar la continuidad de la sesión.
TCP organiza los bytes en una cola lógica y mantiene tres zonas:
La ventana deslizante se desplaza cuando llegan nuevos ACK. Si el receptor anuncia más espacio, el emisor puede seguir empujando datos; si la ventana se encoge, el emisor debe pausar hasta nuevo aviso.
Cada segmento TCP contiene el campo Window Size, conocido como advertised window. Indica cuántos bytes adicionales puede recibir el host antes de saturarse.
| Concepto | Descripción |
|---|---|
| Ventana anunciada | Capacidad disponible en el receptor según sus buffers de socket. |
| Ventana de congestión | Limitación introducida por el control de congestión; depende del estado de la red. |
| Ventana efectiva | El mínimo entre ventana anunciada y ventana de congestión; determina los bytes permitidos en vuelo. |
Las opciones de escalado de ventana, definidas en RFC 7323, permiten multiplicar el valor del campo cuando se necesitan buffers gigantescos, algo común en enlaces de alta velocidad.
Si la aplicación receptora se atasca, el host puede anunciar una ventana cero. El emisor detiene los envíos y activa el temporizador de persistencia. Cada cierto tiempo manda un probe de uno o dos bytes para verificar si la otra parte volvió a tener espacio.
Una ventana cero prolongada suele indicar procesos bloqueados, falta de memoria o filtros intermedios que ralentizan la entrega al socket de usuario.
Sistemas modernos incluyen algoritmos de autoajuste que miden el rendimiento de la aplicación y el hardware subyacente. En Windows, el autotuning regula la Receive Window para exprimir enlaces de alta latencia sin intervención manual.
El emisor también adapta su ritmo: cuando llegan ACK rápidos, interpreta que puede ampliar la ventana; si se acumulan ACK retrasados o aparecen duplicados, reduce la cantidad de datos pendientes. Esta retroalimentación protege al receptor y evita retransmisiones costosas.
El algoritmo de Nagle agrupa bytes pequeños para enviar segmentos llenos, mientras que delayed ACK espera un breve lapso para confirmar varios segmentos a la vez. Combinados, pueden introducir latencia adicional en aplicaciones interactivas.
En una captura de Wireshark se pueden habilitar las columnas “Window Size Value” y “Calculated window size”. Esta última ya incorpora el factor de escalado, lo que facilita interpretar cuántos bytes en vuelo permite el receptor.
Los gráficos de flujo disponibles en Statistics > TCP Stream Graphs muestran cómo la ventana crece a medida que la aplicación consume datos y disminuye cuando se congestiona.
El siguiente script simplifica el comportamiento de la ventana anunciada y muestra cómo el emisor ajusta su ritmo ante ACK lentos o ventanas cero:
from collections import deque
def simular_control_flujo(datos, tam_segmento=8, ventana_inicial=24):
cola = deque([datos[i:i + tam_segmento] for i in range(0, len(datos), tam_segmento)])
ventana = ventana_inicial
en_vuelo = []
secuencia = 0
while cola or en_vuelo:
while cola and sum(len(seg) for _, seg in en_vuelo) + len(cola[0]) <= ventana:
segmento = cola.popleft()
en_vuelo.append((secuencia, segmento))
print(f"ENVÍO {secuencia:04d} -> {segmento!r} (ventana {ventana})")
secuencia += len(segmento)
if not en_vuelo:
break
ack_seq, segmento = en_vuelo.pop(0)
if len(segmento) < tam_segmento // 2:
ventana = max(tam_segmento, ventana // 2)
print(f"ACK lento de {ack_seq:04d}, ventana baja a {ventana}")
else:
ventana += len(segmento)
print(f"ACK {ack_seq:04d} recibido, ventana sube a {ventana}")
texto = "Controlar la ventana evita desbordes del receptor y sostiene la eficiencia."
simular_control_flujo(texto)
Aunque es un modelo sencillo, ayuda a visualizar cómo la ventana efectiva depende de la respuesta del receptor y por qué un ACK lento reduce temporalmente el envío.
Windows permite inspeccionar los perfiles de TCP para verificar si el autotuning del buffer de recepción está habilitado:
Get-NetTCPSetting -SettingName Internet |
Select-Object SettingName, AutoTuningLevelLocal
netsh interface tcp show global | Select-String "Receive Window Auto-Tuning Level"
Get-NetTCPSetting expone el modo de autoajuste por perfil, mientras que netsh interface tcp show global entrega el mismo dato en sistemas heredados.
Si el valor indica disabled, conviene habilitarlo para aprovechar mejor enlaces de alta latencia siempre que las aplicaciones lo permitan.
Aunque son mecanismos distintos, ambos comparten la idea de ventana. El control de flujo protege al receptor; el de congestión protege a la red. El emisor sólo puede enviar la cantidad de datos que cumpla ambas restricciones simultáneamente. Por eso, monitorear la advertised window es tan importante como ajustar parámetros de congestion avoidance.
Con un control de flujo bien configurado, TCP se mantiene estable incluso cuando conviven aplicaciones con ritmos muy diferentes en un mismo enlace.