Networking

TCP/IP & Sockets

TCP/IP es la capa de transporte bajo cada solicitud HTTP, conexión de base de datos y WebSocket. Los sockets son la forma en que tu código se comunica con ella directamente.

intermediate14 min readUpdated 15 sept 2026
server.js
js
// server.js
import { createServer } from "node:net";

const server = createServer((socket) => {
  socket.write("hello\n");
  socket.on("data", (data) => {
    console.log("received:", data.toString().trim());
  });
});

server.listen(9000, () => console.log("tcp://localhost:9000"));
Modelo
Por capas (enlace, IP, transporte, app)
Direccionamiento
Dirección IP + puerto
Fiable
TCP
Rápido
UDP
Handshake
SYN, SYN-ACK, ACK
En Node
node:net

Por que importa

Por qué TCP/IP es importante

Transporte fiable

TCP garantiza una entrega completa y ordenada, razón por la cual HTTP, las bases de datos y el correo electrónico funcionan sobre él.

Todo lo utiliza

Cada solicitud que maneja tu servidor llega a través de una conexión TCP, incluso si un framework oculta los detalles.

Las conexiones tienen un coste

Abrir una conexión TCP requiere un viaje de ida y vuelta más un handshake, por eso es fundamental reutilizarlas.

La imagen completa

Las tres capas del modelo

Las direcciones IP y las rutas gestionan los paquetes, TCP hace que la entrega sea fiable y los sockets son la API que utiliza tu código.

IP

Direccionar y rutear

Los paquetes llevan direcciones de origen y destino y se reenvían salto a salto.

TCP

Fiabilidad

Los números de secuencia, los acuses de recibo y la retransmisión convierten paquetes no fiables en un flujo de datos fiable.

Sockets

Programar

Un socket es el punto final desde el cual tu código lee y escribe, identificado por una dirección y un puerto.

TCP/IP de un vistazo

Las ideas fundamentales

Direcciones IP

IPv4 e IPv6 identifican un host en la red.

Puertos

Un número que identifica un servicio en un host, como el 443 para HTTPS.

Handshake

SYN, SYN-ACK y ACK establecen una conexión y acuerdan las opciones.

Números de secuencia

El orden y la confirmación hacen que la entrega sea fiable.

Control de flujo

Las ventanas evitan que un emisor rápido sature a un receptor lento.

Timeouts

La retransmisión, el keep-alive y el TIME_WAIT gobiernan el ciclo de vida de la conexión.

Una breve historia

El protocolo que sostiene internet

  1. 1974

    Propuesta de TCP

    Cerf y Kahn describen un protocolo para conectar diferentes redes.

    74
  2. 1981

    Estandarización de TCP/IP

    Se especifica la suite de protocolos y posteriormente se adopta como el estándar de internet.

    81
  3. 1983

    Cambio en ARPANET

    La red migra a TCP/IP en un solo día, demostrando su viabilidad a escala.

    83
  4. 1993

    Control de congestión

    Algoritmos como TCP Reno evitan el colapso bajo cargas pesadas.

    93
  5. Hoy

    Sigue siendo la base

    HTTP/3 migra a QUIC sobre UDP, pero TCP sigue transportando la gran mayoría del tráfico.

    Hoy

La guia completa

TCP/IP & Sockets: Todo lo que necesitas saber

¿Qué es TCP/IP?

TCP/IP es el conjunto de protocolos que sostiene internet. IP se encarga del direccionamiento y el enrutamiento de paquetes entre hosts; TCP se sitúa por encima y convierte esos paquetes no confiables en un flujo de bytes ordenado y fiable. Juntos forman la capa de transporte sobre la que funcionan HTTP, las bases de datos, el correo electrónico, WebSocket y casi todo lo demás que hace tu servidor.

Rara vez escribirás código TCP directamente, pero entenderlo explica muchas cosas: por qué las conexiones son costosas, por qué el keep-alive es importante, por qué un pool de base de datos tiene un límite de tamaño y por qué cierto tráfico utiliza UDP en su lugar.

El modelo de capas

Las redes suelen describirse en capas, donde cada una se encarga de una tarea específica:

Capa Tarea Ejemplos
Aplicación Significado HTTP, WebSocket, DNS
Transporte Fiabilidad y puertos TCP, UDP
Internet Direccionamiento y enrutamiento IP, ICMP
Enlace Entrega local Ethernet, Wi-Fi

Cada capa utiliza la que tiene debajo. HTTP no sabe si viaja a través de Ethernet o Wi-Fi; confía en TCP para entregar los bytes, y este a su vez confía en IP para mover los paquetes. Esta separación es la razón por la cual internet puede transportar tantos tipos de tráfico.

Direcciones IP y puertos

Una dirección IP identifica a un host, y un puerto identifica un servicio en ese host. Juntos forman una dirección de socket, como 203.0.113.10:443.

  • Las direcciones IPv4 son de 32 bits (203.0.113.10); las direcciones IPv6 son de 128 bits y se escriben en hexadecimal.
  • Los puertos inferiores a 1024 están reservados para servicios conocidos.
  • Los clientes reciben un puerto efímero durante la vida útil de una conexión.
  • Una conexión se identifica de forma única mediante la tupla completa: dirección de origen, puerto de origen, dirección de destino y puerto de destino.

Esa tupla es la razón por la cual un servidor puede aceptar miles de conexiones en el puerto 443 simultáneamente: el puerto de origen de cada cliente es diferente.

El saludo de tres vías (three-way handshake)

Antes de que fluya cualquier dato, TCP establece una conexión en tres pasos:

  1. El cliente envía un SYN con su número de secuencia inicial.
  2. El servidor responde con un SYN-ACK, confirmando la recepción del cliente y enviando su propio número de secuencia.
  3. El cliente envía un ACK, y la conexión queda establecida.

Esto implica un viaje de ida y vuelta (round trip) antes del primer byte de datos de la aplicación, lo que representa un coste real de latencia. TLS añade otro viaje de ida y vuelta (o dos), y DNS puede añadir otro antes de eso. La reutilización de conexiones existe específicamente para evitar pagar estos costes repetidamente.

Fiabilidad y control de flujo

TCP proporciona fiabilidad a través de varios mecanismos:

  • Números de secuencia que ordenan los bytes, permitiendo que el receptor los reensamble correctamente.
  • Acuses de recibo (Acknowledgements) que confirman la recepción; los datos no confirmados se retransmiten.
  • Sumas de comprobación (Checksums) para detectar la corrupción de datos.
  • Control de flujo que utiliza una ventana de recepción para evitar que un emisor rápido sature a un receptor lento.
  • Control de congestión que adapta la tasa de envío a la red para evitar el colapso.

El resultado es un flujo de bytes que llega completo y en orden, a costa de cierta latencia y sobrecarga (overhead).

UDP: la alternativa rápida

UDP no requiere conexión. Envía datagramas sin handshake, sin orden garantizado y sin retransmisión. Esto podría parecer peor, pero para ciertas cargas de trabajo es preferible:

  • La latencia importa más que la perfección: el video en vivo, la voz y los juegos prefieren perder un frame que recibirlo con retraso.
  • La aplicación gestiona la fiabilidad: QUIC, que impulsa HTTP/3, construye su propia capa de fiabilidad sobre UDP.
  • Consultas pequeñas y sin estado: DNS utiliza tradicionalmente UDP porque una única solicitud y respuesta caben en un solo datagrama.

Elige TCP cuando la exactitud y el orden sean fundamentales, y UDP cuando necesites velocidad y puedas tolerar la pérdida de datos.

Sockets en Node.js

Node expone TCP a través de node:net y UDP a través de node:dgram. Un servidor TCP te entrega un socket por cada conexión.

// echo.js
import { createServer } from "node:net";

const server = createServer((socket) => {
  socket.setKeepAlive(true, 10_000);
  socket.setTimeout(30_000);
  socket.on("timeout", () => socket.destroy());

  socket.on("data", (data) => socket.write(data));
  socket.on("error", (err) => console.error(err));
});

server.listen(9000);

Los sockets son streams: lees eventos data y escribes con socket.write(). Debido a que TCP es un flujo de bytes sin límites de mensaje, los protocolos de aplicación deben definir su propio framing; es por esto que HTTP tiene encabezados con longitudes de contenido y WebSockets tiene frames.

Ciclo de vida y optimización de conexiones

  • Keep-alive reutiliza las conexiones, evitando el handshake en cada solicitud.
  • Pools limitan el número de conexiones concurrentes a una base de datos o servicio.
  • Timeouts cierran las conexiones inactivas o bloqueadas para liberar recursos.
  • TIME_WAIT es un estado normal tras el cierre, pero demasiadas conexiones de corta duración pueden agotar los puertos.
  • Backpressure: socket.write() devuelve false cuando el buffer está lleno, y debes esperar a drain.

La mayor parte de la optimización en producción consiste en reutilizar conexiones y limitar la concurrencia, no en cambiar los parámetros del kernel.

Mejores prácticas

  • Reutiliza las conexiones mediante keep-alive o un pool.
  • Configura timeouts y keep-alive en las conexiones de larga duración.
  • Limita la concurrencia para no agotar los sockets o los descriptores de archivos.
  • Gestiona los errores y la backpressure en cada socket.
  • Utiliza TCP a menos que tengas un motivo específico para usar UDP.
  • Ten en cuenta que TCP es un flujo de bytes (byte stream) y define tu propio framing.
  • Monitoriza el estado TIME_WAIT y el número de conexiones como indicadores de la rotación de conexiones (connection churn).

Errores comunes

  • Abrir una nueva conexión para cada solicitud.
  • Asumir que TCP preserva los límites de los mensajes.
  • Ignorar la contrapresión (backpressure) de socket.write() y almacenar datos sin límite en el búfer.
  • Mantener conexiones de larga duración sin keep-alive o timeouts.
  • Configurar tamaños de pool mucho más grandes de lo que la base de datos puede soportar.
  • Optar por UDP cuando la fiabilidad es realmente importante.

Próximos pasos

TCP/IP es la capa sobre la cual se apoya todo lo demás. Sigue profundizando con la guía de HTTP, comprende los conceptos básicos de red en Cómo funciona Internet y pasa a las conexiones persistentes con WebSockets. Después, inspecciona las conexiones reales en tu máquina con ss o netstat mientras tu servidor gestiona el tráfico.

Eligiendo un transporte

TCP garantiza la entrega ordenada a costa de handshakes y retransmisiones. UDP sacrifica la fiabilidad en favor de la latencia.

TCP
// reliable, ordered stream
const socket = net.connect(9000, "localhost");
socket.write("GET / HTTP/1.1\r\n\r\n");
UDP
// fast, no delivery guarantee
const socket = dgram.createSocket("udp4");
socket.send(Buffer.from("ping"), 9001, "localhost");

Reutilización de conexiones

Abrir una conexión por solicitud implica pagar el coste del handshake cada vez. Keep-alive reutiliza una conexión para múltiples solicitudes.

Preferir
const agent = new http.Agent({
  keepAlive: true,
  maxSockets: 50,
});

fetch(url, { agent });
Evitar
// a fresh connection and
// handshake for every call
for (const url of urls) {
  await fetch(url);
}

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender TCP/IP & Sockets?

Nuestro tutorial interactivo te guia a traves de TCP/IP & Sockets paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.