listen and accept
Picture a receptionist at a desk. First the company announces it is open for callers and sets out a small waiting area (listen). Then, one at a time, the receptionist greets whoever is waiting and walks them to a private room to talk (accept), while new visitors keep arriving and waiting. listen and accept are the two server-side steps that turn a bound socket into one that actually handles incoming TCP connections.
After a server calls bind, it calls listen(fd, backlog) to mark the socket as passive — it will not initiate connections, only receive them — and to set up a queue of pending connections, sized by the backlog number. When a client's three-way handshake completes, the kernel places the finished connection in that queue. The server then calls accept(fd), which removes one ready connection from the queue and hands back a brand-new socket dedicated to that single client. The original listening socket stays open to keep collecting more clients; the new socket is what you read and write to talk to this one client. accept blocks (waits) until a connection is available, unless the socket is non-blocking.
Why it matters: this listen-then-accept pattern is the heartbeat of every TCP server, and the new-socket-per-client design is what lets one server serve many clients at once. It also exposes the core concurrency question: after accept returns a connection, do you handle it in this same thread before accepting the next (serial, simple but slow), spawn a process or thread per connection, or register it in an event loop with I/O multiplexing? The backlog and the kernel's accept queue also matter under load — if clients connect faster than you accept, the queue fills and new connection attempts get refused or dropped, a real bottleneck for busy servers.
A server loops: while true do { conn = accept(listen_fd); handle(conn); }. Each accept returns a fresh socket for one client. The simplest servers handle each conn fully before looping back; busy ones hand conn to a thread or an event loop so the next accept can run immediately.
One listening socket stays open; accept spawns a per-client socket.
accept does not reuse the listening socket for data — it returns a separate socket per connection. The listening socket only produces connections; reading or writing the wrong one is a common beginner bug.