Ports, TCP & UDP
An IP address gets a packet to the right machine; the transport layer gets it to the right program on that machine, and decides what happens when a packet is lost. In this course every service listens on a port (8080 for a Spring Boot app, 5432 for PostgreSQL), every ports: line in a compose.yaml maps one port to another, and most calls between services ride on TCP β while DNS, and HTTP/3, ride on UDP. This page covers ports, the difference between TCP and UDP, the handshake that opens a TCP connection, and what TCP's reliability costs when the network loses packets.
Ports
An IP address identifies a host; a port identifies a specific process on that host. Together, IP:port (called a socket address) identifies a communication endpoint on the network.
Ports are 16-bit numbers (0β65535) divided into three ranges1:
| Range | Name | Use |
|---|---|---|
| 0β1023 | System (well-known) ports | Standard services; on Linux, binding one needs root (or the CAP_NET_BIND_SERVICE capability) |
| 1024β49151 | User (registered) ports | Registered with IANA for common applications |
| 49152β65535 | Dynamic (ephemeral) ports | Assigned to clients for outbound connections |
Well-known ports
| Port | Protocol | Service |
|---|---|---|
| 22 | TCP | SSH (secure shell) |
| 25 | TCP | SMTP (email sending) |
| 53 | UDP/TCP | DNS |
| 80 | TCP | HTTP |
| 443 | TCP (UDP for HTTP/3) | HTTPS |
| 3000 | TCP | Grafana / Node.js development servers |
| 3306 | TCP | MySQL |
| 5432 | TCP | PostgreSQL |
| 6379 | TCP | Redis |
| 8080 | TCP | HTTP (development servers, alternative HTTP) |
| 9090 | TCP | Prometheus |
Ephemeral ports and connections
A server listens on a fixed port; the client's side gets a temporary one. When a browser connects to https://example.com, it connects to port 443 of the server's address, and the operating system picks an ephemeral port (e.g., 52413) for the client side, so the full connection is client_ip:52413 β server_ip:443. Operating systems pick from their own range: IANA suggests 49152β65535, while Linux uses 32768β60999 by default2.
A connection is identified by four numbers β source IP, source port, destination IP, destination port β so one server port can hold thousands of connections at once, one per client socket. You can list the ports your machine is listening on:
ss -tlnp # Linux: TCP sockets in LISTEN state, with the process
lsof -iTCP -sTCP:LISTEN -n -P # macOS (and Linux)
In Docker, ports: - "8081:8080" means "host port 8081 forwards to container port 8080": the service inside still listens on its own port, and the host publishes it under another one (Addressing & NAT).
TCP and UDP
The Transport layer offers two fundamentally different delivery models:
TCP establishes a connection before exchanging data and guarantees that3:
- Every byte is delivered exactly once, in order
- Lost packets are automatically retransmitted
- The sender slows down if the receiver or the network is overwhelmed (flow and congestion control)
Use when: correctness matters more than speed β HTTP/1.1 and HTTP/2, database connections, SSH, message brokers.
UDP sends datagrams with no connection setup, no delivery guarantee, and no ordering4.
- No handshake β lower latency
- No retransmission β if a packet is lost, it is gone
- Application must handle ordering and reliability if needed
Use when: a late packet is worthless or the application brings its own reliability β DNS queries, video calls, online gaming, VoIP, and QUIC (the transport under HTTP/3).
| TCP | UDP | |
|---|---|---|
| Connection | Required (3-way handshake) | None |
| Delivery guarantee | Yes β retransmits lost packets | No |
| Ordering | Yes β bytes arrive in sequence | No |
| Latency | Higher: one round trip to connect, and waits for lost data | Lower |
| Use cases | HTTP/1.1, HTTP/2, SSH, databases | DNS, video, VoIP, gaming, QUIC / HTTP/3 |
The three-way handshake
Before any data flows, a TCP client and server agree on initial sequence numbers β the counters each side uses to number its bytes, so the other can acknowledge them and spot what is missing:
sequenceDiagram
participant C as Client<br/>ephemeral port 52413
participant S as Server<br/>port 443
C->>S: SYN (seq = x)
S-->>C: SYN-ACK (seq = y, ack = x+1)
C->>S: ACK (ack = y+1) + first data (request)
Note over C,S: connection established after one round trip
S-->>C: data (response), ack = bytes received so far
C->>S: ACK The handshake costs one round trip before the first byte of the request leaves the client. HTTPS adds a TLS handshake on top β one more round trip with TLS 1.35. On a 77 ms SΓ£o Paulo β Virginia path that is about 150 ms before the request is even sent, which is why clients and services reuse connections (HTTP keep-alive, connection pools) instead of opening a new one per request.
A port that nobody listens on answers the SYN with a reset (RST): that is the "connection refused" error. A SYN that gets no answer at all (a firewall dropped it, the host is down) is retried until the client gives up: a "timeout".
What reliability costs
TCP's guarantee has a price, and it is paid in time. The sender keeps every segment until the receiver acknowledges it. If no acknowledgement arrives before the retransmission timer (RTO) runs out, it sends the segment again, and doubles the timer for the next attempt6. Meanwhile the receiver may already hold the segments that came after the lost one β but TCP promises bytes in order, so it cannot hand them to the application yet. One lost segment holds back everything behind it: head-of-line blocking.
UDP pays nothing of the kind: what arrives is delivered at once, and what is lost stays lost. Compare both over the same link, with the same losses:
Try it
The run starts at 10% loss, and segments 4 and 7 are lost. Press play. UDP is done at 230 ms with 18/20 segments β two gaps that never get filled. TCP delivers all 20, in order, at 380 ms: 2 retransmissions, and 15 segments that had already arrived waited in the buffer behind segment 4. Set the loss to 0%: UDP finishes at 230 ms and TCP at 310 ms β the 80 ms difference is the handshake's round trip. At 20%, a retransmission is lost as well and the timer doubles: 3 retransmissions, done at 780 ms. At 30%, UDP keeps only 16/20, while TCP needs 7 retransmissions and 1,540 ms.
The simulator keeps only the timer. Real TCP also retransmits early when duplicate acknowledgements show a gap (fast retransmit), and slows its sending rate when it sees loss (congestion control) β so on a lossy network throughput drops, not just latency. Head-of-line blocking is also why HTTP/3 moved to QUIC, which runs over UDP and retransmits per stream: a lost packet of one response no longer stalls the others sharing the connection7.
Key takeaways
- A port picks the process on a host;
IP:portis a socket address, and a connection is identified by both ends' addresses and ports. - Servers listen on fixed ports; clients get an ephemeral port from the operating system (32768β60999 on Linux).
- TCP opens a connection with a three-way handshake (one round trip) and then delivers every byte, once, in order.
- Reliability costs time: a lost segment waits for the retransmission timer, and the segments behind it wait too (head-of-line blocking).
- UDP delivers what arrives, with no setup and no waiting; DNS, real-time media and QUIC (HTTP/3) build on it.