Napisałem serwer, który nasłuchuje nadchodzących połączeń TCP i klientów łączących się z nim. Kiedy zamykam serwer i uruchamiam go ponownie na tym samym porcie, czasami pojawia się komunikat o błędzie EADDRINUSE podczas wywoływania bind (...) (kod błędu: 98 w systemie Linux). Dzieje się tak, mimo że ustawiam opcję ponownego użycia gniazda.Adres, który jest już używany z akceptorem asio boost
Błąd nie występuje cały czas, ale wydaje się, że zdarza się częściej, gdy klienci są połączeni z serwerem i wysyłają dane podczas zamykania. Chyba problem polega na tym, że nadal są oczekujące połączenia podczas zamykania serwera (temat powiązany: https://stackoverflow.com/questions/41602/how-to-forcibly-close-a-socket-in-time-wait).
Po stronie serwera używam boost :: asio :: ip :: tcp :: acceptor. Inicjuję go opcją "reuse_address" (patrz http://beta.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/basic_socket_acceptor.html). Oto fragment kodu:
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();
Akceptor jest zamknięty:
acceptor.close();
Próbowałem też za pomocą acceptor.cancel() wcześniej, ale miał ten sam efekt. Kiedy wystąpił ten błąd, nie mogę ponownie uruchomić serwera na tym samym porcie przez dłuższy czas. Ponowne uruchomienie sieci pomaga, ale nie jest rozwiązaniem trwałym.
Czego mi brakuje?
Każda pomoc będzie bardzo ceniona! :)
Czy twój serwer rozwidla procesy potomne? –
również, czy na pewno gniazdo jest w stanie TIME_WAIT? W takim przypadku możesz chcieć pobrać wyjście 'netstat -ap'. –
Sam, dziękuję bardzo za twój wkład! Pomógł mi znaleźć rozwiązanie mojego problemu. Okazało się, że ustawiłem opcję ponownego użycia adresu dla akceptora, ale nie dla wszystkich innych połączeń. Jeszcze raz bardzo dziękuję za pomoc! – Alexander