Search code examples
csocketsposix-select

How to know if a new client is connecting to a socket with select()


My question is : How, (with select()) can I know if a new client is connecting on my server ? A can't just use accept because accept() is blocking...

Example : I have two clients set on fd user1 (fd = 4) and user2 (fd = 5). So, I use select to know who write on the socket :

  FD_ZERO(read_fds);
  FD_SET(user1, read_fds);
  FD_SET(user2, read_fds);
  error = select(user2 + 1, read_fds, NULL, NULL, NULL);
  if (FD_ISSET(user1, read_fds) == 1)
     printf("user1 talks.\n");
  ...

But I want know if a new user is connecting to the server, what can I do ? I have try :

  FD_ZERO(read_fds);
  FD_SET(user1, read_fds);
  FD_SET(user2, read_fds);
  FD_SET((user2 + 1), read_fds);
  error = select(user2 + 2, read_fds, NULL, NULL, NULL);
  if (FD_ISSET(users2 + 1) == 1)
  {
      printf("New user.\n");
      accept(..., ...);
  }
  ...

But with this code, select return -1 every time...

A solution ? ^^


Solution

  • You have to store the connected clients somewhere, like a list for example.

    struct client_node
    {
        int sockfd;
        /* Other data that might be needed */
        struct client_node *next;
    };
    
    struct client_node *client_list = NULL;
    
    /* ... */
    
    FD_ZERO(&read_fds);
    FD_SET(listening_socket, &read_fds);
    
    int maxfd = listening_socket;
    
    for (struct client_node *c = client_list; c; c = c->next)
    {
        FD_SET(c->sockfd, &read_fds);
        maxfd = MAX(maxfd, c->sockfd);
    }
    
    int res = select(maxfd + 1, &read_fds, NULL, NULL, NULL);
    

    As for the blocking issue for accept, as you can see I have added the a socket (variable listening_socket) that is the socket you are listening on. When select says you can read from it, it means there is a new connection and that you can call accept.