TCP, UDP, ports, and sockets
Ports and sockets
Use port numbers and socket endpoints to identify the communicating processes behind an IP connection.
8 minute lesson
An IP address identifies an interface, but several applications can share that address. Your laptop runs a browser, a mail client, and a dozen background services, all using the same IP at once. TCP and UDP port numbers help deliver traffic to the correct process.
A socket endpoint combines an address, transport protocol, and port. A TCP connection is commonly identified by four values: source address, source port, destination address, and destination port. That four-tuple is why thousands of browser tabs can talk to the same web server without their data getting mixed up — each connection differs in at least one value.
See it live
Start a tiny web server and inspect it:
python3 -m http.server 8000 &
ss -lntp | grep 8000
LISTEN 0 5 0.0.0.0:8000 0.0.0.0:* users:(("python3",pid=41285,fd=3))
The server is listening: address 0.0.0.0 (all interfaces), TCP port 8000, owned by process 41285. On macOS, use lsof -nP -iTCP:8000 for the same answer.
Now connect to it from another terminal and look at the established connection:
curl -s localhost:8000 > /dev/null &
ss -tnp | grep 8000
# ESTAB 127.0.0.1:8000 127.0.0.1:52814
There’s the four-tuple in action. Servers listen on known or configured ports — here, 8000. Clients usually choose temporary ports: 52814 was picked by the kernel from the ephemeral range and will be different next time. A web server might listen on TCP port 443 while each browser connection uses a different client port.
Stop the test server with kill %1 when you’re done.
“Is the port open?” is the wrong question
A port is not a physical hole and it is not globally open or closed. It matters together with an address, protocol, interface binding, listening process, and firewall path.
A frequent real-world bug: a service binds to 127.0.0.1:8000 instead of 0.0.0.0:8000. From the machine itself everything works. From any other machine, connections are refused — nothing is listening on the externally reachable address. The ss -lntp output makes this visible instantly: check the local address column, not just the port number.
So when something can’t connect, don’t ask “is the port open?” Ask: which process is listening, on which address, for which protocol, and does the path from the client actually reach it?
Lesson completed