Networking in C · intermediate · ~10 min

listen() and accept() — the server side

Transition a socket from bound to listening, then accept incoming connections.

Lesson

listen(fd, backlog) marks fd as accepting connections; backlog is the kernel's queue depth for half-finished SYN/ACK handshakes (32 is fine for labs).

accept(fd, &peer, &peer_len) blocks until a client connects, then returns a new fd for that one connection. The original fd keeps listening for the next client.

Server loop skeleton:

listen(srv_fd, 32);
for (;;) {
    struct sockaddr_in peer; socklen_t plen = sizeof peer;
    int client_fd = accept(srv_fd, (struct sockaddr *)&peer, &plen);
    if (client_fd < 0) { perror("accept"); continue; }
    /* talk to client_fd, then close it */
    close(client_fd);
}

Code examples

int srv = socket(AF_INET, SOCK_STREAM, 0);
/* … setsockopt + bind on 127.0.0.1:8080 … */
listen(srv, 32);

struct sockaddr_in peer; socklen_t plen = sizeof peer;
int client = accept(srv, (struct sockaddr *)&peer, &plen);
write(client, "hi\n", 3);
close(client);
close(srv);

Common mistakes

  • Forgetting to close client_fd after each connection. fd leak.
  • Treating srv_fd and client_fd as the same thing. They're separate sockets.

Summary

listen() puts a bound socket into listening mode. accept() returns a fresh fd for each incoming connection. Close the per-client fd when done.

Practice with these exercises