选择系统调用不扫描超过2个描述符

时间:2017-11-05 17:52:04

标签: c linux sockets

我正在编写服务于多个客户端的服务器程序(最多5个)。当任何客户端连接到服务器时,服务器将描述符存储到数组中,并通过选择系统调用检查这些描述符中的任何活动。但是,它只能从任何2个客户端读取,并且根本不会提供其他客户端请求。这是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);
        }

    }



  }



 }

每个客户端在休眠一段时间后发送和接收数据(通过命令行提供)。示例:client1 5sec,client2 4sec等等......

客户的代码是:

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]));  
 }

提前致谢。

1 个答案:

答案 0 :(得分:2)

这一行错了:

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

select()的第一个参数不应该是NUM_CLIENT + 1,而是最大文件描述符值(在你调用FD_SET()的所有文件描述符值上),加上一个。