2010-02-05 14 views
10

Ho un socket che ascolta su alcune porte. Invio il segnale SIGSTOP al thread che attende sulla porta (usando accept) e lo interrompo. poi chiudo il fd della presa che ho aspettato. Ma per la prossima esecuzione del mio progetto, non mi permette di riascoltare su quella porta. Il mio programma è in C++ sotto linux. Cosa devo fare?Socket listen non si slega in C++ sotto linux

Alcune parti del mio codice sono: filettatura 1:

void* accepter(void *portNo) { 
int newsockfd; 
sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) { 
perror("ERROR opening socket"); 
} 
struct sockaddr_in server; 
bzero((char *) & server, sizeof (server)); 
server.sin_family = AF_INET; 
server.sin_port = htons(*(int*) portNo); 
server.sin_addr.s_addr = INADDR_ANY; 
if (bind(sockfd, (struct sockaddr *) & server, sizeof (struct sockaddr_in)) < 0) { 
perror("ERROR on binding"); 
} 

listen(sockfd, 50); 
while (true) { 
struct sockaddr_in client; 
socklen_t clientLen = sizeof (struct sockaddr_in); 
newsockfd = accept(sockfd, (struct sockaddr *) & client, &clientLen); 
if (accepterFlag) { 
    break; 
} 
if (getpeername(newsockfd, (sockaddr *) & client, &clientLen) == -1) { 
    perror("getpeername() failed"); 
} 
sem_wait(setSem); 
FD_SET(newsockfd, &set); 
if (maxFd < newsockfd) { 
    maxFd = newsockfd; 
} 
sem_post(setSem); 
} 

filettatura 2:

listenerFlag = true; 
accepterFlag = true; 
sleep(1); 
pthread_kill(listenerThread, SIGSTOP); 
pthread_kill(accepterThread, SIGSTOP); 
close(sockfd); 
sem_wait(setSem); 
for (int i = 1; i <= maxFd; i++) { 
if (FD_ISSET(i, &set)) { 
    close(i); 
} 
} 
sem_post(setSem); 

Grazie.

+0

Forse prova a chiudere il fd del socket all'interno del thread in accettazione mentre termina? –

+1

Sei sicuro di voler inviare 'SIGSTOP'? Qualcuno manderà un 'SIGCONT' dopo? Non sarei sorpreso se i socket non potessero essere chiusi finché un thread (interrotto) si trova ancora all'interno di una chiamata 'accept' su quel socket. (Hai detto che hai anche interrotto il thread, io proprio non lo vedo.) –

risposta

21

Lo sapevate che le prese sono in genere tenuti in una sorta di limbo per un minuto o due dopo aver finito l'ascolto su di loro per evitare che le comunicazioni destinate al precedente processo a venire al tuo? Si chiama stato 'TIME_WAIT'.

Se si desidera sovrascrivere tale comportamento, utilizzare setsockopt per impostare il flag SO_REUSEADDR sul socket prima di ascoltarlo.

+4

Controlla anche SO_LINGER. http://www.developerweb.net/forum/archive/index.php/t-2982.html – jfawcett

+0

Lo sapevo in Java. È lo stesso per C++? – Shayan

+3

Sì, è una cosa TCP piuttosto che una lingua, quindi si applica ovunque. –

1

Credo che il problema è che non si è chiuso bene la presa e/o la vostra presa program.The probabilmente esiste ancora nel sistema operativo. controllalo con qualcosa come nestat -an. Dovresti anche controllare se il tuo processo è terminato. Se è terminato correttamente, dovrebbe aver chiuso il socket.

Che cosa si dovrebbe fare è:

  • interrompere il filo con un segnale.
  • una volta interrotta, la filettatura dovrebbe chiudere correttamente la presa prima della fine.
  • quindi è possibile uscire in modo pulito dal programma.

my2cents,

+0

Vedere la domanda modificata, per favore. – Shayan

+0

Ok. Quindi SO_REUSEADDR è la chiave :-) – neuro