Мое клиентское приложение использует boost::asio::ip::tcp::socket
для подключения к удаленному серверу.
Если приложение теряет соединение с этим сервером (например, из-за сбоя или остановки сервера), я бы хотел, чтобы оно пыталось повторно подключаться через регулярные промежутки времени до тех пор, пока оно не выполнится.
Что мне нужно сделать на стороне клиента, чтобы аккуратно обработать разъединение, привести в порядок, а затем повторно предпринять попытку повторного соединения?
В настоящее время интересные фрагменты моего кода выглядят примерно так.
I connect
вот так:
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)
}
Где метод runIOServer()
просто:
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();
}
И если какой-либо из обработчиков асинхронного чтения возвращает ошибку, он просто вызывает этот 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();
}
.. который пытается изящно отключиться, а затем уведомляет наблюдателя, который начнет вызывать connect()
с интервалом в пять секунд, пока он не будет повторно подключен.
Что еще мне нужно сделать?
В настоящее время это кажется работать. Если я убиваю сервер, к которому он подключен, я получаю ожидаемую ошибку "End of file"
в моих обработчиках чтения, и mydisconnect()
вызывается без проблем.
Но когда он пытается снова подключиться и терпит неудачу, я вижу отчет "socket.shutdown error: Invalid argument"
. Это только потому, что я пытаюсь отключить сокет, который не ожидает чтения / записи? Или это нечто большее?