2010-11-16 11 views
10

Escribí un servidor que está escuchando conexiones TCP entrantes y clientes que se conectan a ella. Cuando apago el servidor y lo reinicio en el mismo puerto, a veces aparece el mensaje de error EADDRINUSE al llamar a bind (...) (código de error: 98 en Linux). Esto sucede a pesar de que estoy configurando la opción para reutilizar el socket.Dirección ya en uso con el aceptador boost asio

El error no ocurre todo el tiempo, pero parece que ocurre con mayor frecuencia cuando los clientes están conectados al servidor y envían datos mientras se apaga. Supongo que el problema es que todavía hay conexiones pendientes mientras el servidor está cerrado (tema relacionado: https://stackoverflow.com/questions/41602/how-to-forcibly-close-a-socket-in-time-wait).

En el lado del servidor, estoy usando boost :: asio :: ip :: tcp :: acceptor. Inicializo con la opción "reuse_address" (vea http://beta.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/basic_socket_acceptor.html). Aquí está el fragmento de código:

using boost::asio::ip::tcp; 
acceptor acceptor::acceptor(io_service); 
endpoint ep(ip::tcp::v4(), port); 
acceptor.open(ep.protocol()); 
acceptor.set_option(acceptor::reuse_address(true)); 
acceptor.bind(ep); 
acceptor.listen(); 

El aceptor se cerró con:

acceptor.close(); 

También he intentado usar acceptor.cancel() antes de eso, pero tenía el mismo efecto. Cuando se produjo este error, no puedo reiniciar el servidor en el mismo puerto durante bastante tiempo. Reiniciar la red ayuda, pero no es una solución permanente.

¿Qué me estoy perdiendo?

¡Cualquier ayuda sería muy apreciada! :)

+1

¿su servidor es fork procesos secundarios? –

+1

también, ¿está seguro de que el socket está en el estado TIME_WAIT? Es posible que desee obtener el resultado 'netstat -ap' cuando esto suceda. –

+1

Sam, muchas gracias por su aporte! Me ayudó a encontrar la solución a mi problema. Resultó que configuré la opción de dirección de reutilización para el aceptador, pero no para todas las otras conexiones. ¡De nuevo, muchísimas gracias por vuestra ayuda! – Alexander

Respuesta

1

Estos fueron originalmente un comentario a la pregunta.


¿su servidor fork procesos de niño? Además, ¿estás seguro de que el socket está en el estado TIME_WAIT? Es posible que desee obtener la salida netstat -ap cuando esto ocurra

0

Cuando resuelve estos problemas "por la fuerza", parece que está llamando problemas en la cabeza, ¿no?

Existe una razón por la cual el comportamiento predeterminado requiere que espere, de lo contrario la red podría confundir, por ejemplo, el ACK de la conexión anterior para que sea ACK para la nueva conexión.

No permitiría que esta "solución" se incluya en las versiones de lanzamiento de mi equipo.

Recuerde, cuando la probabilidad de error es muy baja, la prueba es extremadamente difícil.

+0

Gracias por su respuesta. Dividí mi respuesta debido a limitaciones de espacio. Recuerdo la situación primero: se estaba ejecutando un servidor y se escuchaba en un puerto fijo para las conexiones entrantes. Luego, los clientes se conectaron a él en ese puerto. En algún momento, detuve el servidor, lo que hizo que todos los clientes cerraran su conexión al servidor. (Estoy bastante seguro de que cerré las conexiones tanto en el servidor como en el lado del cliente correctamente.) – Alexander

+0

Luego, inicié el servidor nuevamente. Sin embargo, el servidor no podía comenzar a escuchar en el mismo puerto porque las conexiones de los clientes no tenían la opción de reutilización y el puerto todavía estaba reservado.La pregunta ahora es ¿cómo puedo reutilizar una dirección que ya está marcada en uso por el sistema operativo aunque todas las conexiones se cerraron correctamente sin usar la opción de reutilización? – Alexander

+3

Solo aceptar esperar (lo que puede llevar bastante tiempo) no es una solución aceptable para un servidor. Creí (y sigo creyendo) que la configuración de la opción de reutilización es apropiada en este caso. Sin embargo, estoy muy interesado en una solución alternativa y me alegraría si pudieras dar alguna pista. (En una nota al margen: La solución propuesta arriba funciona muy bien. Usamos el servidor extensamente y no encontramos ningún problema relacionado con las conexiones. Por supuesto, esto no garantiza que esté 100% libre de errores). – Alexander

Cuestiones relacionadas