Difficulty: Beginner
What is a port and what is a socket? How can a server handle thousands of clients on the same port 443?
This question separates people who memorised port numbers from people who understand how a connection is actually identified. Start with an analogy: an IP address is the address of a big apartment building, and a port number is the flat number. The IP gets your packet to the right machine, the port gets it to the right process on that machine.
A port is a 16-bit number, so from 0 to 65535, that the transport layer (TCP or UDP) uses to multiplex many conversations over one IP address. Ports are split into three ranges: well-known ports 0 to 1023 (HTTP 80, HTTPS 443, SSH 22, DNS 53, SMTP 25, FTP 21, and these usually require root privileges to bind), registered ports 1024 to 49151, and dynamic or ephemeral ports 49152 to 65535 (Linux by default uses 32768 to 60999) which the OS hands out to clients as source ports.
A socket is the programming endpoint of a network connection, the object your code holds. Loosely, it is the combination of an IP address and a port, like 10.0.0.5:51000. A TCP connection is uniquely identified by a 5-tuple: protocol, source IP, source port, destination IP, destination port. That is the key to the famous follow-up. A server listening on port 443 does not run out of ports after 65535 clients, because the connection identity includes the client's IP and client's port too. Thousands of clients can all connect to server_ip:443 as long as each client tuple is different.
Here is how it works mechanically on the server. The server creates one listening socket with socket, bind, and listen. When a client connects and the handshake finishes, accept returns a brand new connected socket, distinct from the listening socket, with its own 5-tuple. The listening socket keeps waiting on port 443, and each accepted socket is used for one client. So the server has one socket in LISTEN state and N sockets in ESTABLISHED state, all with local port 443.
The real limit is different. A single client machine connecting to one specific server IP and port can use at most about 28000 to 64000 ephemeral ports, so around that many concurrent connections to that one destination. This is the origin of port exhaustion problems on proxies and load balancers. On the server side the limits are file descriptors and memory, which is the famous C10K problem, solved by event-driven I/O such as epoll.
Also mention that UDP sockets are connectionless: a single UDP socket can receive datagrams from many senders, and identification is by destination IP and port only, with the sender address reported per datagram. And that TCP and UDP port spaces are separate, so TCP 53 and UDP 53 are different endpoints, which is why DNS can use both. Finally, SO_REUSEADDR lets a server rebind quickly after restart, which connects to TIME_WAIT behaviour that we cover separately.
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", 8080))
srv.listen(128)
print("listening on 8080")
while True:
conn, addr = srv.accept() # new socket per client
print("client", addr)
data = conn.recv(1024)
conn.sendall(data)
conn.close()
Each accept returns a new socket with a different client port, though the server local port stays 8080.
Port, Socket, Client-Server, Port Ranges, Multiplexing