2016-05-15 55 views
0

我正在練習POSIX編程套接字,我有我的服務器,當我終止其客戶端之一,函數pselect獲取錯誤錯誤filedescriptor(我認爲它errno = EBADF),你能幫我我並寫我如何可以在我的代碼中避免它?糟糕的filedescriptor錯誤處理

這裏是我寫的:

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; 
} 
+0

當你得到pselect失敗時,你能打印出'maxfd'的值嗎? –

+0

@MarkPlotnick是的,我可以,但這個FD不再有效,因爲客戶端關閉。 – HackTheGibson

+0

我希望看到的是'maxfd'是否大於'fd_set'的大小。 'add_new_client'總是返回一個正數嗎?那麼maxfd永遠不會減少。 –

回答

1

您確定您已關閉套接字選擇。當您關閉一個插座時,您需要將其從FD組中移除。你對這一套的處理看起來很樂觀。例如,您無法確定添加新客戶端是否會增加最大FD。我也不明白你爲什麼要從套件中刪除監聽套接字,更別說兩次了,然後重新開始。您需要查看select()的一些示例代碼。這非常奇怪。