【问题标题】:Bad filedescriptor error handling错误的文件描述符错误处理
【发布时间】:2016-05-15 20:14:32
【问题描述】:

我正在练习 POSIX 编程套接字,我的服务器有以下问题,当我终止它的一个客户端时,函数 pselect 得到错误错误文件描述符(我认为它的 errno=EBADF),你能帮我写下如何我在我的代码中避免了它?

这是我写的:

void doServer(int fd) {
//fd is the listening socket (there is only one)
int maxfd = fd;
//base, and reading fd set
fd_set base_rfds, rfds;
int i;
sigset_t mask, oldmask;
//zero out base fd set
FD_ZERO(&base_rfds);
//add listening socket to base fd set
FD_SET(fd, &base_rfds);
//add SIGINT to blocking signal mask
sigemptyset (&mask);
sigaddset (&mask, SIGINT);
sigprocmask (SIG_BLOCK, &mask, &oldmask);
//main server loop (block on pselect untill fd changes or we get signal)
while(!stop){
    rfds=base_rfds;
    //call pselect with oldmask to not block SIG_INT
    if(pselect(maxfd+1,&rfds,NULL,NULL,NULL,&oldmask)>0){

        if(FD_ISSET(fd,&rfds)){
            //connect client
            maxfd+=add_new_client(fd, &base_rfds);
            //remove listening socket from reading fd set
            FD_CLR(fd,&rfds);
        }
        //remove listening socket from base fd set
        FD_CLR(fd,&base_rfds);
        handle_connection(rfds,&base_rfds,maxfd);
        //add listening socket back into base fd set
        FD_SET(fd,&base_rfds);
    }
    else{
        if(EINTR==errno) continue;
        ERR("select");
    }
}
//close all of fd's from connected clients
for(i=0;i<maxfd;i++) 
    if(FD_ISSET(i,&base_rfds) && TEMP_FAILURE_RETRY(close(i))<0)ERR("close");
sigprocmask (SIG_UNBLOCK, &mask, NULL);
}

编辑: 这里是 add_new_client 函数:

int add_new_client(int sfd, fd_set *base_rfds){
int nfd,new_flags;
//accept now if we can (non-blocking)
if((nfd=TEMP_FAILURE_RETRY(accept(sfd,NULL,NULL)))<0) {
    if(EAGAIN==errno||EWOULDBLOCK==errno) return 0;
    ERR("accept");
}
//remember to make the fd non-blocking
//get current flags, add O_NONBLOCK
new_flags = fcntl(nfd, F_GETFL) | O_NONBLOCK;
//apply new flags
fcntl(nfd, F_SETFL, new_flags);
//add discriptor to base fd set
FD_SET(nfd,base_rfds);
return 1;
}

【问题讨论】:

  • pselect 失败时能否打印出maxfd 的值?
  • @MarkPlotnick 是的,我可以,但是自从客户端关闭后,这个 fd 不再有效。
  • 我想看看maxfd 是否会大于fd_set 的大小。 add_new_client 是否总是返回正数?那么 maxfd 将永远不会减少。
  • @MarkPlotnick yes add_new_client 总是返回 1 或 0 if(EAGAIN==errno||EWOULDBLOCK==errno) return 0;

标签: c sockets unix posix errno


【解决方案1】:

您正在选择已关闭的套接字。当你关闭一个套接字时,你需要将它从 FD 集中移除。你对这一套的处理似乎相当乐观。例如,您不能确定添加新客户端是否真的会增加最大 FD。我也不明白你为什么要从集合中删除监听套接字一次,更不用说两次,然后恢复它。您需要查看select() 的一些示例代码。这一切都很奇怪。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多