Networking

TCP/IP & Sockets

TCP/IP is the transport layer under every HTTP request, database connection and WebSocket. Sockets are how your code talks to it directly.

intermediate14 min readUpdated Sep 15, 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"));
Model
Layered (link, IP, transport, app)
Addressing
IP address + port
Reliable
TCP
Fast
UDP
Handshake
SYN, SYN-ACK, ACK
In Node
node:net

Why it matters

Why TCP/IP matters

Reliable transport

TCP guarantees ordered, complete delivery, which is why HTTP, databases and email all run on it.

Everything uses it

Every request your server handles arrives over a TCP connection, even if a framework hides the details.

Connections have a cost

Opening a TCP connection takes a round trip plus a handshake, which is why reusing them matters.

The big picture

The three layers of the model

IP addresses and routes packets, TCP makes delivery reliable, and sockets are the API your code uses.

IP

Address and route

Packets carry source and destination addresses and are forwarded hop by hop.

TCP

Reliability

Sequence numbers, acknowledgements and retransmission turn unreliable packets into a reliable stream.

Sockets

Program

A socket is the endpoint your code reads from and writes to, identified by address and port.

TCP/IP at a glance

The core ideas

IP addresses

IPv4 and IPv6 identify a host on the network.

Ports

A number that identifies a service on a host, such as 443 for HTTPS.

Handshake

SYN, SYN-ACK and ACK establish a connection and agree on options.

Sequence numbers

Ordering and acknowledgement make delivery reliable.

Flow control

Windows prevent a fast sender from overwhelming a slow receiver.

Timeouts

Retransmission, keep-alive and TIME_WAIT govern connection lifecycle.

A short history

The protocol that carries the internet

  1. 1974

    TCP proposed

    Cerf and Kahn describe a protocol for connecting different networks.

    74
  2. 1981

    TCP/IP standardised

    The protocol suite is specified and later adopted as the internet standard.

    81
  3. 1983

    ARPANET switches

    The network moves to TCP/IP on a single day, proving it at scale.

    83
  4. 1993

    Congestion control

    Algorithms like TCP Reno prevent collapse under heavy load.

    93
  5. Today

    Still the foundation

    HTTP/3 moves to QUIC over UDP, but TCP carries the vast majority of traffic.

    Today

The complete guide

TCP/IP & Sockets: Everything you need to know

What is TCP/IP?

TCP/IP is the protocol suite that carries the internet. IP is responsible for addressing and routing packets between hosts; TCP sits on top and turns those unreliable packets into a reliable, ordered stream of bytes. Together they are the transport layer under HTTP, databases, email, WebSockets and almost everything else your server does.

You rarely write TCP code directly, but understanding it explains a lot: why connections are expensive, why keep-alive matters, why a database pool has a size limit, and why some traffic uses UDP instead.

The layer model

Networking is usually described in layers, each handling one job:

Layer Job Examples
Application Meaning HTTP, WebSocket, DNS
Transport Reliability and ports TCP, UDP
Internet Addressing and routing IP, ICMP
Link Local delivery Ethernet, Wi-Fi

Each layer uses the one below it. HTTP does not know whether it travels over Ethernet or Wi-Fi; it relies on TCP to deliver bytes, which relies on IP to move packets. This separation is why the internet can carry so many kinds of traffic.

IP addresses and ports

An IP address identifies a host, and a port identifies a service on that host. Together they form a socket address, such as 203.0.113.10:443.

  • IPv4 addresses are 32-bit (203.0.113.10); IPv6 addresses are 128-bit and written in hex.
  • Ports below 1024 are reserved for well-known services.
  • Clients get an ephemeral port for the lifetime of a connection.
  • A connection is uniquely identified by the full tuple: source address, source port, destination address and destination port.

That tuple is why a server can accept thousands of connections on port 443 at once: each client’s source port differs.

The three-way handshake

Before any data flows, TCP establishes a connection in three steps:

  1. The client sends a SYN with its initial sequence number.
  2. The server replies with SYN-ACK, acknowledging the client and sending its own sequence number.
  3. The client sends ACK, and the connection is established.

This costs one round trip before the first byte of application data, which is a real latency cost. TLS adds another round trip (or two), and DNS may add another before that. Connection reuse exists specifically to avoid paying these costs repeatedly.

Reliability and flow control

TCP provides reliability through a few mechanisms:

  • Sequence numbers order the bytes, so the receiver can reassemble them correctly.
  • Acknowledgements confirm receipt, and unacknowledged data is retransmitted.
  • Checksums detect corruption.
  • Flow control uses a receive window so a fast sender cannot overwhelm a slow receiver.
  • Congestion control adapts the sending rate to the network, avoiding collapse.

The result is a stream of bytes that arrives complete and in order, at the cost of some latency and overhead.

UDP: the fast alternative

UDP is connectionless. It sends datagrams with no handshake, no ordering and no retransmission. That sounds worse, but for some workloads it is better:

  • Latency matters more than perfection: live video, voice and games prefer a lost frame to a delayed one.
  • The application handles reliability: QUIC, which powers HTTP/3, builds its own reliability on top of UDP.
  • Small, stateless queries: DNS traditionally uses UDP because a single request and response fit in one datagram.

Choose TCP when correctness and ordering matter, and UDP when you need speed and can tolerate loss.

Sockets in Node.js

Node exposes TCP through node:net and UDP through node:dgram. A TCP server hands you a socket per connection.

// 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);

Sockets are streams: you read data events and write with socket.write(). Because TCP is a byte stream with no message boundaries, application protocols must define their own framing, which is why HTTP has headers with content lengths and WebSockets have frames.

Connection lifecycle and tuning

  • Keep-alive reuses connections, avoiding the handshake for every request.
  • Pools cap the number of concurrent connections to a database or service.
  • Timeouts close idle or stuck connections so resources are freed.
  • TIME_WAIT is a normal state after closing, but too many short-lived connections can exhaust ports.
  • Backpressure: socket.write() returns false when the buffer is full, and you should wait for drain.

Most production tuning is about reusing connections and limiting concurrency, not changing kernel parameters.

Best practices

  • Reuse connections with keep-alive or a pool.
  • Set timeouts and keep-alive on long-lived connections.
  • Limit concurrency so you do not exhaust sockets or file descriptors.
  • Handle errors and backpressure on every socket.
  • Use TCP unless you have a specific reason for UDP.
  • Understand that TCP is a byte stream and define your own framing.
  • Monitor TIME_WAIT and connection counts as a signal of connection churn.

Common mistakes

  • Opening a new connection for every request.
  • Assuming TCP preserves message boundaries.
  • Ignoring socket.write() backpressure and buffering unbounded data.
  • Leaving long-lived connections without keep-alive or timeouts.
  • Setting pool sizes far larger than the database can handle.
  • Reaching for UDP when reliability actually matters.

Where to go next

TCP/IP is the layer everything else stands on. Build on it with the HTTP guide, understand the network basics in How the Internet Works, and move to persistent connections with WebSockets. Then inspect real connections on your machine with ss or netstat while your server handles traffic.

Choosing a transport

TCP guarantees ordered delivery at the cost of handshakes and retransmits. UDP trades reliability for latency.

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");

Reusing connections

Opening a connection per request pays the handshake every time. Keep-alive reuses one connection for many requests.

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

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

FAQ

Frequently asked questions

Keep learning

Related topics from the roadmap.

$ start learning

Ready to start learning TCP/IP & Sockets?

Our interactive tutorial walks you through TCP/IP & Sockets step by step — with quizzes and real code you can run in the browser.