2016-05-15 3 views
0

Ich übe POSIX-Programmierung Sockets und ich habe folgendes Problem mit meinem Server, wenn ich einen seiner Clients zu beenden, die Funktion pselect bekommt Fehler schlecht filedescriptor (ich denke, es ist errno = EBADF), könnten Sie mir helfen und schreibe wie kann ich es in meinem Code vermeiden?Bad Filescriptor Fehlerbehandlung

Hier ist, was ich schrieb:

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

EDIT: hier ist add_new_client Funktion:

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

Können Sie den Wert von 'maxfd' ausdrucken, wenn Sie den Fehler pselect erhalten? –

+0

@MarkPlotnick ja ich kann, aber diese fd ist nicht mehr gültig seit Client geschlossen. – HackTheGibson

+0

Was ich gerne sehen würde, ist, ob 'maxfd' jemals größer wird als die Größe eines 'fd_set'. Gibt 'add_new_client' immer eine positive Zahl zurück? Dann wird maxfd niemals abnehmen. –

Antwort

1

Sie befinden sich auf einem Sockel sind die Auswahl, die Sie geschlossen haben. Wenn Sie einen Socket schließen, müssen Sie ihn aus dem FD-Set entfernen. Ihr Umgang mit diesem Set scheint ziemlich optimistisch. Zum Beispiel können Sie nicht sicher sein, dass das Hinzufügen eines neuen Clients wirklich die maximale FD erhöhen wird. Ich verstehe auch nicht, warum du den hörenden Sockel einmal aus dem Set entfernst, geschweige denn zweimal, und ihn dann wieder einsetzt. Sie müssen sich einen Beispielcode für select() ansehen. Das ist alles sehr seltsam.