2010-02-05 9 views
10

Tengo un socket que escucha en algún puerto. Envío la señal SIGSTOP al hilo que espera en el puerto (usando aceptar) y termino. luego cierro el fd del socket que esperé. Pero para la próxima ejecución de mi proyecto, no me permite escuchar en ese puerto de nuevo. Mi programa está en C++ en Linux. ¿Qué debo hacer?Socket listen no se desvincula en C++ bajo Linux

Algunas partes de mi código son: Tema 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); 
} 

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

Gracias.

+0

¿Quizás intente cerrar el fd del socket dentro del hilo de aceptación cuando está terminando? –

+1

¿Seguro que quieres enviar 'SIGSTOP'? ¿Alguien va a enviar un 'SIGCONT' más tarde? No me sorprendería si los sockets no se pudieran cerrar por completo siempre y cuando algún hilo (detenido) aún esté dentro de una llamada 'accept' en ese socket. (Dijiste que también terminaste el hilo, simplemente no lo veo). –

Respuesta

21

¿Sabía que los enchufes se mantienen típicamente en una especie de limbo durante un minuto o dos después de que haya terminado de escuchar sobre ellos para evitar que las comunicaciones destinadas para el proceso anterior viene a la suya? Se llama el estado 'TIME_WAIT'.

Si desea anular ese comportamiento, utilice setsockopt para establecer el indicador SO_REUSEADDR en el socket antes de escucharlo.

+4

También verifique SO_LINGER. http://www.developerweb.net/forum/archive/index.php/t-2982.html – jfawcett

+0

Lo sabía en Java. ¿Es lo mismo para C++? – Shayan

+3

Sí, es algo de TCP más que de lenguaje, por lo que se aplica en todas partes. –

1

Creo que el problema es que no se ha cerrado correctamente la toma y/o su toma programa.El probable que todavía existe en el sistema operativo. compruébalo con algo como nestat -an. También debe verificar si su proceso ha finalizado. Si ha terminado correctamente, debería haber cerrado su socket.

Lo que debe hacer es:

  • interrumpir su hilo con una señal.
  • cuando se interrumpe su hilo debe cerrar limpiamente el zócalo antes del final.
  • luego puede salir limpiamente de su programa.

my2cents,

+0

Consulte la pregunta editada, por favor. – Shayan

+0

Ok. Entonces SO_REUSEADDR es la clave :-) – neuro

Cuestiones relacionadas