anil
anil

Reputation: 158

Select system call not scanning more than 2 descriptors

I am writing a Server program serving to Multiple client(max 5). As any client connects to server, server stores the descriptor into an array and checks for any activity in those descriptors via Select system call. But, it is only reading from any 2 clients only and rest client requests are not being served at all. Here is a code for Server

#define NUM_CLIENT 5

void main(int argc,char** argv)
{
 int master_sock, newSocket, err;
 struct sockaddr_in Server_addr, Client_addr;
 char buf[100]; 
 int i=0;
 int activity;

 //socket descriptors for select
 fd_set readfd;
 int client_fd[NUM_CLIENT]={-1,-1,-1,-1,-1};    

 //Socket creation
 master_sock= socket(AF_INET,SOCK_STREAM,0);
 if(master_sock<0){
    perror("socket");
    return;
 }

 //structure filling for listening to the port
 Server_addr.sin_family = AF_INET;
 Server_addr.sin_port = htons(atoi(argv[1]));
 Server_addr.sin_addr.s_addr = INADDR_ANY;

 //Binding to the Address and port filled in structure
 err = bind(master_sock,(struct sockaddr*)&Server_addr,sizeof(Server_addr));
 if(err<0){
    perror("socket");
    return;
 }

 printf("\nlistening to port");
 err = listen(master_sock,NUM_CLIENT);  //to inform, the willlingness to accept connections.
 if(err<0){
    perror("Listen");
    return;
 }
 printf("\nAccepting connection");

 while(1)
 {
    //Select modifies the objects in structure for any activity,
    // So we need to load them again.
    FD_ZERO(&readfd);   //clearing the readfd list
    FD_SET(master_sock,&readfd);    //adding the descriptor for select to listen

    for(i=0;i<NUM_CLIENT;i++){      
        if(client_fd[i] != -1){
            FD_SET(client_fd[i],&readfd);   //Add socket to the list

        }           
    }
    //Descriptors loaded..

    //start Select operation....

    activity = select(NUM_CLIENT+1,&readfd,NULL,NULL,NULL); //wait here until any activiy occurs
    if(activity < 0){
        perror("Select");break;
    }
    printf("\nactivity happened in socket...");

    //If activity related to master socket i.e. New client is trying to connect.
    if( FD_ISSET(master_sock,&readfd) ) {
        printf("\nactivity in master socket...");
        int len = sizeof(Client_addr);

        //Accept the connection
        newSocket = accept(master_sock, (struct sockaddr*)&Client_addr ,&len);  //blocking call
        if(newSocket<0){
            perror("accept");return;
        }
        printf("\nNew connection accepted");    

 //     puts("Receiving data");
        if( recv(newSocket,buf,100,0) > 0 )     //blocking call
            printf("\n%s",buf);
        else
            strcpy(buf,"hey");

//      puts("Sending data");   
        if( send(newSocket,buf,strlen(buf),0) < 0 )
            perror("send");


        //creating client database of descriptors
        for(i=0;i<NUM_CLIENT;i++){
            printf("\nfd[%d] = %d\n",i,client_fd[i]);           
            if(client_fd[i] == -1){
                client_fd[i]= newSocket;
                //FD_SET(newSocket,&readfd);    //Add socket to the list
                //printf("\nfd[%d] = %d\n",i,client_fd[i]);         
                break;
            }

        }

    }

    //If activity(read or write) in other sockets, check it out
    printf("\nChecking Activity in Other File Descriptors\n");
    for(i=0;i<NUM_CLIENT;i++){

        if(FD_ISSET(client_fd[i],&readfd)){

            printf("\nactivity in client %d ...",i);
 //     puts("Receiving data");
            if( recv(client_fd[i],buf,100,0) > 0 )  //blocking call
                puts(buf);  
            else
                strcpy(buf,"hello");
 //     puts("Sending data");   
            if( send(client_fd[i],buf,strlen(buf)+1,0) == -1 )
                perror("send");
                //printf("\n%s",buf);
        }

    }



  }



 }

And every client sends and receive data after sleeping for given time(provided via command line). Example: client1 5sec ,client2 4sec and so on...

The code for client is :

void main(int argc, char** argv)
{
 int fd, err;
 char buf[100],buf2[100];
 struct sockaddr_in server;

 fd = socket(AF_INET,SOCK_STREAM,0);
 if(fd<0){
    perror("socket");return;
 }

I2A(buf,getpid());  //Integer to array conversion, returns array
strcat(buf,"Hello");

printf("%s\n",buf);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1])); //Host to network
server.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("Connecting with server\n");
if( connect(fd, (struct sockaddr*)&server,sizeof(server) ) < 0) {
    perror("connect");return;
}
printf("Connected with server\n");

while(1){

//  printf("Sending data\n");
 if( send(fd,buf,20,0) < 0)
    perror("send");

 // printf("Receiving data\n"); 
 if( recv(fd,buf2,sizeof(buf2),0) >0 )
    printf("%s\n",buf2);
 sleep(atoi(argv[2]));  
 }

Thanks in advance.

Upvotes: 0

Views: 50

Answers (1)

Jeremy Friesner
Jeremy Friesner

Reputation: 73039

This line is wrong:

activity = select(NUM_CLIENT+1,&readfd,NULL,NULL,NULL); //wait here until any activiy occurs

The first argument to select() should not be NUM_CLIENT+1, but rather the maximum file descriptor value (across all of the file descriptor values that you called FD_SET() on)), plus one.

Upvotes: 2

Related Questions