Moja aplikacja kliencka używa boost::asio::ip::tcp::socket
do łączenia się ze zdalnym serwerem. Jeśli aplikacja utraci połączenie z tym serwerem (np. Z powodu awarii serwera lub zamknięcia), chciałabym spróbować ponownie połączyć się w regularnych odstępach czasu, dopóki się to nie uda.Jak mogę ponownie podłączyć gniazdo boost :: po odłączeniu?
Co muszę zrobić po stronie klienta, aby wyczyścić obsługę rozłączenia, posprzątać, a następnie wielokrotnie próbować ponownych połączeń?
Obecnie interesujące fragmenty mojego kodu wyglądają mniej więcej tak.
I connect
tak:
bool MyClient::myconnect()
{
bool isConnected = false;
// Attempt connection
socket.connect(server_endpoint, errorcode);
if (errorcode)
{
cerr << "Connection failed: " << errorcode.message() << endl;
mydisconnect();
}
else
{
isConnected = true;
// Connected so setup async read for an incoming message.
startReadMessage();
// And start the io_service_thread
io_service_thread = new boost::thread(
boost::bind(&MyClient::runIOService, this, boost::ref(io_service)));
}
return (isConnected)
}
Jeżeli metoda runIOServer()
tylko:
void MyClient::runIOService(boost::asio::io_service& io_service)
{
size_t executedCount = io_service.run();
cout << "io_service: " << executedCount << " handlers executed." << endl;
io_service.reset();
}
A jeśli któryś z obsługą asynchroniczny odczytu zwróci błąd następnie po prostu wywołanie tej metody disconnect
:
void MyClient::mydisconnect(void)
{
boost::system::error_code errorcode;
if (socket.is_open())
{
// Boost documentation recommends calling shutdown first
// for "graceful" closing of socket.
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorcode);
if (errorcode)
{
cerr << "socket.shutdown error: " << errorcode.message() << endl;
}
socket.close(errorcode);
if (errorcode)
{
cerr << "socket.close error: " << errorcode.message() << endl;
}
// Notify the observer we have disconnected
myObserver->disconnected();
}
.. który próbuje łaski całkowicie odłączyć, a następnie powiadomi obserwatora, który rozpocznie wywoływanie connect()
w pięciosekundowych odstępach czasu, aż zostanie ponownie podłączony.
Czy jest coś jeszcze, co muszę zrobić?
Obecnie wygląda na to, że zadziała. Jeśli zabiję serwer, do którego jest on podłączony, otrzymuję oczekiwany błąd "End of file"
w moich procedurach odczytu i wywołanie mydisconnect()
bez żadnych problemów.
Ale gdy następnie próbuje ponownie połączyć się i nie działa, widzę raport "socket.shutdown error: Invalid argument"
. Czy to dlatego, że próbuję zamknąć gniazdo, które nie ma odczytu/zapisu oczekujących na to? A może to coś więcej?
Jakie jest Twoje uzasadnienie wywołania zamknięcia, jeśli wykryłeś już koniec drugiego końca połączenia? –
@samm: Czy to nie jest zalecane? Myślałem, że mogą być oczekujące operacje na gnieździe, które muszą być anulowane przy pomocy 'shutdown()'. Głównie robię to jednak dla uproszczenia: ta sama metoda 'mydisconnect()' jest wywoływana, jeśli chcę normalnie rozłączyć, lub jeśli jakiekolwiek operacje asynchroniczne zwrócą błąd. – GrahamS
Nie jestem pewien, czy jest to zalecane, czy nie. Gdzie będą te oczekujące dane lub operacje? Drugi koniec połączenia nie ma. –