Sockets & Ports
The API where applications meet the network — and what a “connection” actually is to the kernel.
What a Socket Is
A socket is the OS’s handle for a network endpoint — to your program it’s just a file descriptor you read() and write(). A TCP connection is uniquely identified by the 4-tuple: (src IP, src port, dst IP, dst port). That’s why one server port can hold thousands of connections — each client arrives from a different IP:port, so each 4-tuple is distinct.
| Port range | Name | Use |
|---|---|---|
| 0–1023 | Well-known | 80 HTTP, 443 HTTPS, 22 SSH, 53 DNS — need root to bind |
| 1024–49151 | Registered | 5432 Postgres, 6379 Redis, 3306 MySQL |
| 49152–65535 | Ephemeral | Kernel assigns these to outgoing client connections |
The Server Lifecycle
accept() returns a new socket for each client; the listening socket keeps listening. The kernel even completes handshakes in the background and queues them (the backlog) until you accept.A Real Server — the Accept Loop
import socket srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) srv.bind(("0.0.0.0", 9000)) # all interfaces, port 9000 srv.listen(128) # backlog of pending handshakes while True: conn, addr = srv.accept() # blocks until a client connects data = conn.recv(4096) conn.sendall(data) # echo it back conn.close()
One loop, one client at a time. Real servers wrap accept in threads, processes, or an event loop (epoll) — that story is in the OS pillar’s I/O guide.
SO_REUSEADDR matters: without it a restarted server can’t rebind while old connections sit in TIME_WAIT — the classic “Address already in use”.Reading netstat / ss Like a Pro
# listening sockets + owning process ss -tlnp # established connections to port 443 ss -tn state established '( dport = :443 )' # count connections per state — spot TIME_WAIT floods ss -tan | awk '{print $1}' | sort | uniq -c
| State | Meaning |
|---|---|
LISTEN | Server waiting for connections |
ESTABLISHED | Live connection, data can flow |
TIME_WAIT | Closed locally; lingering ~60s to catch stray packets |
CLOSE_WAIT | Peer closed; your app hasn’t called close() — a leak signature |
Interview Questions
How can one port serve thousands of clients?
Connections are keyed by the full 4-tuple (src IP, src port, dst IP, dst port), not the server port alone. Every client arrives from a distinct IP:port, so the kernel demultiplexes thousands of sockets all “on” port 443.
What does the backlog in listen(128) mean?
The queue of connections the kernel has already handshaken but the app hasn’t accept()ed yet. If it fills, new SYNs are dropped or refused — clients see timeouts under accept-loop stalls.
Lots of CLOSE_WAIT sockets — what does it tell you?
The remote side closed but our application never called close() on its end — a file-descriptor leak in our code (missing close in an error path), not a network problem.
Ephemeral ports — what and why?
Short-lived ports (~49152-65535) the kernel auto-assigns to outgoing connections as the client side of the 4-tuple. Exhausting them (many rapid short connections) causes connect failures; fixes include keep-alive and connection pooling.