【问题标题】:select keeps waiting indefinitely选择无限期地等待
【发布时间】:2012-05-12 07:40:22
【问题描述】:

我在尝试 select() 时得到了一个奇怪的结果。

fd_set tempset,set; //set of descriptors

FD_ZERO(&set); //initialize descriptor set to NULL

FD_SET(serversock,&set); //add server's socket to descriptor set 'set'

timeout.tv_sec=2;
timeout.tv_usec=0;

while(1){

tempset=set;
timeout.tv_sec=2;
timeout.tv_usec=0;

printf("%s","Waiting on select\n");

int ret=select(FD_SETSIZE,&tempset,NULL,NULL,&timeout);

if(ret==0) printf("timeout ");

else if(ret==-1){
    printf("Error occured\n");
    exit(0);
}

else if(ret>0){ //socket ready for reading

    for(i=0;i<FD_SETSIZE;i++){

    if(FD_ISSET(i,&tempset)){ //check if it's serversock

        if(i==serversock){
              //accept connection and read/write
              printf("Client connected\n");

    }//i==serversock close

    }
}//for ends 
}

当我删除行 printf("%s","Waiting on select\n");选择无限期地等待。但是,当我重新插入线路时,一切正常(通过客户端连接测试)

我错过了什么吗?

提前致谢!

【问题讨论】:

  • 在这个循环中每次调用 select 之前需要重新初始化文件描述符集。
  • 您可能有 stdio 缓冲效果。尝试在“超时”消息中添加换行符,即printf("timeout \n");,看看这是否会改变您观察到的内容。我敢打赌,您的 select() 实际上每 2 秒超时一次,但如果没有顶部的 printf 刷新 stdout 行缓冲区,您将看不到它。
  • 是的,在超时后添加新行就可以了。谢谢!但是为什么需要刷新 stdout 才能使 select 工作?

标签: c linux sockets select


【解决方案1】:

您在滥用FD_SETSIZE,您根本不应该直接使用它。您只需将一个套接字放入fd_set,因此根本不需要循环遍历它(但如果确实需要,请改用fd_set.fd_count 成员)。

试试这个:

fd_set set;
timeval timeout;

while(1){ 
    FD_ZERO(&set);
    FD_SET(serversock, &set);

    timeout.tv_sec = 2; 
    timeout.tv_usec = 0; 

    printf("%s","Waiting on select\n"); 

    int ret = select(serversock+1, &set, NULL, NULL, &timeout); 

    if (ret==0){
        printf("timeout "); 
    }

    else if (ret==-1){ 
        printf("Error occured\n"); 
        exit(0); 
    } 

    else if (ret>0){ //socket ready for reading 
        ... = accept(serversock, ...);
        printf("Client connected\n"); 
    }
}

或者:

fd_set set;
timeval timeout;
int max_fd = 0;

while(1){ 
    FD_ZERO(&set);

    FD_SET(serversock, &set);
    max_fd = serversock;

    // FD_SET() other sockets and updating max_fd as needed...

    timeout.tv_sec = 2; 
    timeout.tv_usec = 0; 

    printf("%s","Waiting on select\n"); 

    int ret = select(max_fd+1, &set, NULL, NULL, &timeout); 

    if (ret==0){
        printf("timeout "); 
    }

    else if (ret==-1){ 
        printf("Error occured\n"); 
        exit(0); 
    } 

    else if (ret>0){ //socket(s) ready for reading 
        for (u_int i = 0; i < set.fd_count; ++i){
            ... = accept(set.fd_array[i], ...);
            printf("Client connected\n"); 
        }
    }
} 

【讨论】:

    猜你喜欢
    • 2021-03-09
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多