My client application uses a boost::asio::ip::tcp::socket
to connect to a remote server.
If the app loses connection to this server (e.g. due to the server crashing or being shutdown) I would like it to attempt a re-connect at regular intervals until it succeeds.
What do I need to do on the client-side to cleanly handle a disconnect, tidy up and then repeatedly attempt reconnects?
Currently the interesting bits of my code look something like this.
I connect
like this:
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)
}
Where the runIOServer()
method is just:
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();
}
And if any of the async read handlers return an error then they just call this disconnect
method:
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();
}
..which attempts to gracefully disconnect and then notifies an observer, which will start calling connect()
at five second intervals until it gets reconnected.
Is there anything else I need to do?
Currently this does seem to work. If I kill the server that it is connected to I get the expected "End of file"
error at my read handlers and mydisconnect()
is called without any issues.
But when it then attempts to re-connect and fails I see it report "socket.shutdown error: Invalid argument"
. Is this just because I am attempting to shutdown a socket that has no read/writes pending on it? Or is it something more?
shutdown()
. I mainly just do it for simplicity though: the samemydisconnect()
method is called if I want to disconnect normally, or if any async operations return an error. – Iridosmineclose()
is all that is required. Data still in flight is still delivered. – Tillman