I basically have a server set up and I'm accepting new clients(UNIX) and i'm using select() command to wait for activity on file descriptor but I'm not sure how to write from the clients side and then read it on the servers side

FD_ZERO(&readfds);
FD_SET(server_sockfd, &readfds);
FD_SET(STDIN_FILENO, &readfds); 
while (1) {
   testfds = readfds;
   select(4 + MAXCLIENTS, &testfds, NULL, NULL, NULL);
   for (fd = 0; fd < 4 + MAX_CLIENTS; fd++) {
     if (FD_ISSET(fd, &testfds)) {
        if (fd == server_sockfd) { /* new connection request */
           client_sockfd = accept(server_sockfd, NULL, NULL);
           if (num_clients < MAXCLIENTS) {
              FD_SET(client_sockfd, &readfds);
              num_clients++;
           } else {
              sprintf(message, "XSorry, too many clients.  Try again later.\n");
              write(client_sockfd, message, strlen(message));
              close(client_sockfd);
           }
        } else if (fd == STDIN_FILENO) { 
           fgets(kb_message, BUFSIZ + 1, stdin);
           if (strcmp(kb_message, "quit\n") == 0) {
              sprintf(message, "XServer is shutting down.\n");
              for (fd2 = 4; fd2 < 4 + MAX_CLIENTS; fd2++) {
                 if (FD_ISSET(fd2, &readfds)) {
                    write(fd2, message, strlen(message));
                    close(fd2);
                 }
              }
              close(server_sockfd);
              exit(EXIT_SUCCESS);
           } else {
              sprintf(message, "M%s", kb_message);
              for (fd2 = 4; fd2 < 4 + MAX_CLIENTS; fd2++)
                 if (FD_ISSET(fd2, &readfds))
                    write(fd2, message, strlen(message));
           }
        } else { /* client leaving */
           close(fd);
           FD_CLR(fd, &readfds);
           num_clients--;
        }
     }
  }

}

How would I handle write request from clients and then write back to them, would it be under "else" and how can I check if client is exiting or writing.

Thanks

Comments

@Roberto: You might want to re-edit the code :)

Accepted Answer

You are correct in thinking you need the read code in your 'else' block. If a file descriptor triggers and it isn't stdin or the 'connect' descriptor, then it is one of your clients attempting to send you data. When one of those file descriptors is triggered in the select, you need to call 'read' on that descriptor to read the data into the buffer. The read command will return you the number of bytes read. If this is a positive number, then it indicates the client has sent you data. If it is zero, then that indicates that the client has ended the TCP connection to your server.

The else block will look something like:

 else 
  {
     //Existing connection has data for us to read
     if((nBytes = read(fd, buffer, MAXBUFFER)) <= 0) 
     {
        if(nBytes == 0)
        {
          //Actually, its sending us zero bytes, connection closed
          printf("Socket %d hung up\n", fd;
        }
     else
          printf ("Read Error"\n)
  }

Also, Follow Nikolai N Fetissov's advice above and make sure that when client's connect you store their fd in a permanent fd_set structure, as the one you are using is being modified by the select call.

Written by bdk
This page was build to provide you fast access to the question and the direct accepted answer.
The content is written by members of the stackoverflow.com community.
It is licensed under cc-wiki