Roberto
Roberto

Reputation: 3

Using sockets to read from client side

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

Upvotes: 0

Views: 3334

Answers (4)

muruga
muruga

Reputation: 2122

else 
{
  bzero(buf,100);
     n=read(i,buf,100); // Read the client message 
            buf[n]='\0';
       if(n==0) // Check the client is closed or not 
      {

              printf("%d is closed\n",i);
              close(i);
              FD_CLR(i, &master);
              if(i==fdmax)
              fdmax--;

       }
       else
       {
            n=strlen(buf);

        write(1,buf,n);
        fflush(stdout);

          write(1,"Enter the message\n",18);
          bzero(buf,100);
          read(0,buf,100);
            buf[n]='\0';
          write(i,buf,n);
          fflush(stdout);
       }
    } 

Notes: After accept the client, Add the client in the fd set. Then read the message from the client If the message is equal to 0, then the client is closed. If you want to send the message to the client, using the client fd, you can send to the client

Upvotes: 0

bdk
bdk

Reputation: 4839

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.

Upvotes: 1

Nikolai Fetissov
Nikolai Fetissov

Reputation: 84151

The most common mistake with select(2) is not re-initializing the descriptor sets, since second, third, and forth arguments are input-output parameters.

Setup an fd_set, for reading before the outer loop, add listening socket descriptor to it, enter the loop, make a copy of the this fd_set and give the copy to select(2). When new connection arrives, add its descriptor to the original fd_set. Same for closed socket (error or EOF on read(2)) - remove the descriptor from the original fd_set.

Hope this helps.

Upvotes: 2

Carl Norum
Carl Norum

Reputation: 224844

Your problem might be that you have a variable called read. It's going to mask one of hte functions you need to use - the read() system call to get data out of the socket. The client puts it in with write(). You might also want to check the return value from select(), which will tell you how many of the file descriptors are ready for reading. Then you can check which ones using FD_ISSET(). It looks like you're doing that part already (except you seem to be checking the wrong variable?)... just call read() on that file descriptor to get out the data the client wrote.

Upvotes: 0

Related Questions