Server Example (The GNU C Library)

#### 16.9.7 Byte Stream Connection Server Example ¶

The server end is much more complicated. Since we want to allow multiple clients to be connected to the server at the same time, it would be incorrect to wait for input from a single client by simply calling `read` or `recv`. Instead, the right thing to do is to use `select` (see Waiting for Input or Output) to wait for input on all of the open sockets. This also allows the server to deal with additional connection requests.

This particular server doesn’t do anything interesting once it has gotten a message from a client. It does close the socket for that client when it detects an end-of-file condition (resulting from the client shutting down its end of the connection).

This program uses `make_socket` to set up the socket address; see Internet Socket Example.

    #include <arpa/inet.h>
    #include <stdio.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>

    #define PORT    5555
    #define MAXMSG  512

    int
    read_from_client (int filedes)
    {
      char buffer[MAXMSG];
      int nbytes;

      nbytes = read (filedes, buffer, MAXMSG);
      if (nbytes < 0)
        {
          /* Read error. */
          perror ("read");
          exit (EXIT_FAILURE);
        }
      else if (nbytes == 0)
        /* End-of-file. */
        return -1;
      else
        {
          /* Data read. */
          fprintf (stderr, "Server: got message: `%s'\n", buffer);
          return 0;
        }
    }

    int
    main (void)
    {
      extern int make_socket (uint16_t port);
      int sock;
      fd_set active_fd_set, read_fd_set;
      int i;
      struct sockaddr_in clientname;
      socklen_t size;

      /* Create the socket and set it up to accept connections. */
      sock = make_socket (PORT);
      if (listen (sock, 1) < 0)
        {
          perror ("listen");
          exit (EXIT_FAILURE);
        }

      /* Initialize the set of active sockets. */
      FD_ZERO (&active_fd_set);
      FD_SET (sock, &active_fd_set);

      while (1)
        {
          /* Block until input arrives on one or more active sockets. */
          read_fd_set = active_fd_set;
          if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
            {
              perror ("select");
              exit (EXIT_FAILURE);
            }

          /* Service all the sockets with input pending. */
          for (i = 0; i < FD_SETSIZE; ++i)
            if (FD_ISSET (i, &read_fd_set))
              {
                if (i == sock)
                  {
                    /* Connection request on original socket. */
                    int new;
                    size = sizeof (clientname);
                    new = accept (sock,
                                  (struct sockaddr *) &clientname,
                                  &size);
                    if (new < 0)
                      {
                        perror ("accept");
                        exit (EXIT_FAILURE);
                      }
                    fprintf (stderr,
                             "Server: connect from host %s, port %hd.\n",
                             inet_ntoa (clientname.sin_addr),
                             ntohs (clientname.sin_port));
                    FD_SET (new, &active_fd_set);
                  }
                else
                  {
                    /* Data arriving on an already-connected socket. */
                    if (read_from_client (i) < 0)
                      {
                        close (i);
                        FD_CLR (i, &active_fd_set);
                      }
                  }
              }
        }
    }