2009-08-06 24 views
5

Actualmente estoy escribiendo una pequeña aplicación de servidor, y mi problema es que cuando cierro mi aplicación (o mejor, presiono el botón terminar en eclipse), el socket a veces permanece abierto, así que cuando ejecute mi aplicación la próxima vez, bind() fallará con "Dirección ya en uso". ¿Cómo puedo cerrar correctamente los enchufes cuando sale el programa? Ya puseEl socket permanece abierto después de cerrar el programa (C++)

close(mySocket); 

en los destructores de clase, pero eso no parece cambiar nada.

+0

¿Estás seguro de que los destructores se están ejecutando? ¿Puedes poner alguna salida o un punto de quiebre allí para ver? –

+0

TCP está estandarizado "en el cable" pero no en el nivel API. Por lo tanto, una de las cosas más importantes al hacer preguntas con respecto a TCP es divulgar la plataforma. –

Respuesta

2

http://hea-www.harvard.edu/~fine/Tech/addrinuse.html debería responder a muchas de sus preguntas. Tiendo a usar SO_REUSEADDR para solucionar ese problema.

+0

Ok, si lo hago bien, este tipo de ignora que el socket todavía se informa como en uso. Pero, ¿hay alguna manera de cerrarlo correctamente en primer lugar? – fresskoma

+0

Sí. Llamar 'cerrar' en él. – Geo

+0

Sí, pero dónde. Dónde debería llamarlo para que se ejecute cuando finalice mi aplicación. – fresskoma

-1

¿Estás seguro de que tu aplicación no se está ejecutando de alguna manera en segundo plano?

+0

Sí, casi. matar -9 definitivamente debería cerrarlo, ¿no es así? De todos modos, no puedo encontrarlo cuando grep sobre ps -A. – fresskoma

+0

Kill -9 debería encargarse de eso. Eso es sorprendente – Juan

+0

Excepto que kill -9 significa "CIERRE ESTA COSA AHORA MISMO", no "diga esto para que se cierre correctamente". No llamará a los destructores. –

2

se ha marcado la opción SO_REUSEADDR? Por lo que dices, parece que no.

3

Usa netstat para averiguar en qué estado se encuentra tu endpoint. Supongo que está en TIME_WAIT y no está completamente cerrado. Este es el comportamiento correcto para TCP, y existe para permitir que lleguen segmentos perdidos que aún podrían estar fuera en el éter y no causar problemas. La duración de TIME_WAIT es algo así como 2 * MSL, es decir, el doble de la vida útil máxima de un segmento en la red, lo que asegura que incluso un segmento que se retransmite se maneje adecuadamente.

Como han señalado otros, SO_REUSEADDR es su amigo siempre que el extremo del extremo lejano sea diferente cada vez. Ese es el caso común, pero a veces la gente hace cosas raras como vincular a un cliente a un puerto específico, y en ese caso todavía obtendrá un EADDRINUSE b/c TCP define una sesión como ambos extremos.

0

No olvide verificar el valor de retorno de close. Volverá a 0 cuando el socket se cierra con éxito. Devolverá -1 si falló.

Cuestiones relacionadas