CodeBlanks Logo Icon CodeBlanks

listen and accept

Learn to accept connections with listen and accept.

listen and accept

listen(fd, backlog) puts the socket into passive listening mode. backlog is the length of the pending connection queue; usually 5. After this the socket is ready to accept connections.

accept(fd, NULL, NULL) accepts an incoming connection and returns a new descriptor. The original socket keeps listening; the new descriptor is for communicating with the client. accept blocks until a connection arrives. The client connects with connect; details in the next lesson.

Accepting connections

When the server calls accept, it waits until a client connects with connect. When a connection arrives, accept returns a new descriptor.

You exchange data over this descriptor with send and recv. For testing, you can run server and client in the same program with fork: the parent listens, the child connects. This guarantees ordering and makes the output deterministic.

Practice Accept a connection

Create a socket, call bind and listen(listen_fd, 1). Fork a child; in the child call connect(cfd, (struct sockaddr *)&addr, sizeof(addr)). In the parent call int client_fd = accept(listen_fd, NULL, NULL); and printf("accepted\n");. Use path /tmp/cb_l.sock.

Starter code

main.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>

// Create socket, bind and listen
// Fork a child, child does connect
// Parent accept and print

int main(void) {
    return 0;
}

Sample solution

main.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>

int main(void) {
    int listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    struct sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, "/tmp/cb_l.sock", sizeof(addr.sun_path) - 1);
    unlink("/tmp/cb_l.sock");
    bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr));
    listen(listen_fd, 1);
    pid_t pid = fork();
    if (pid == 0) {
        int cfd = socket(AF_UNIX, SOCK_STREAM, 0);
        connect(cfd, (struct sockaddr *)&addr, sizeof(addr));
        close(cfd);
        _exit(0);
    }
    int client_fd = accept(listen_fd, NULL, NULL);
    printf("accepted\n");
    close(client_fd);
    close(listen_fd);
    unlink("/tmp/cb_l.sock");
    return 0;
}

Expected output

accepted

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 listen call

Question
listen(fd, ____);
Answer
listen(fd, 5);

Explanation: A backlog of 5 is the pending queue length.

2 Match listening steps

Term Meaning
listen Starts listening
accept Accepts connection
backlog Queue length
fork Creates process

3 What does accept return?

  • The old descriptor
  • A byte count
  • A new descriptor Correct answer
  • An address struct

Explanation: accept returns a new descriptor for the client.

All lessons in Advanced