Я разрабатываю асинхронную клиентскую программу TCP с использованием boost :: asio. У меня есть вопрос относительно принятой практики: в случае, если сокет сломается или отключается, я должен позволить моему потоку io_context выйти (т.е. не выдавать никаких запросов async_connect и позволить моему методу запуска выйти) и позволить основному потоку перезапустить io_context и попытаться async_connect или я должен дать запрос async_connect чтобы остановить мой поток io_context от выхода (т.е. выдать любой запрос async_connect и не позволить моему методу выполнения выйти). Какой подход более приемлемый.
Согласно моему предположению, преимущество разрешения выхода потока io_context заключается в том, что вы начинаете с нового чистого потока (вы начинаете с нового сланца), а недостатком является большее количество вычислений, требований к ресурсам и времени выполнения.
Напротив, если я продолжу с моим текущим потоком io_context, то есть я даю запрос async_connect, чтобы остановить мой поток io_context, я экономлю на вычислениях, требованиях к ресурсам и времени выполнения, но я не получаю чистый лист.
Какой из двух методов более целесообразен?
void AsyncSocket::recieveHandler(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
fmt::print("In recieve handler, Error Code : {}\nBytes recieved : {}\n", ec.message(), bytes_transferred);
try
{
std::atomic_store(std::addressof(this->receivingData), false);
if (ec not_eq boost::system::errc::success)
{
#ifdef _DEBUG
fmt::print("Error in WebSocket::recieveHandler. Error : {0}\n", ec.message());
#endif // _DEBUG
LOG_ERROR << ec.message();
switch (ec.value())
{
case boost::asio::error::eof :
case boost::asio::error::connection_reset :
case boost::asio::error::connection_aborted :
case boost::asio::error::network_reset :
case boost::asio::error::network_down :
case boost::asio::error::network_unreachable :
if (this->isSocketAlive() and this->socket.is_open())
this->socket.close();
std::atomic_store(std::addressof(this->socketAlive), false);
//this->connectSocket(); //[1]
return;
default:
break;
}
}
else
{
this->readDataQueue.push(std::string(reinterpret_cast <const char *> (this->readDataBuffer.data()), bytes_transferred));
std::atomic_store(std::addressof(this->readComplete), true);
}
}
catch (const std::exception& ex)
{
#ifdef _DEBUG
fmt::print("Error in WebSocket::sendHandler. Error : {0}\n", ex.what());
#endif // _DEBUG
LOG_ERROR << "Exception : " << ex.what() << "Data : " << this->writeDataQueue.front();
}
this->recieveDataSocket();
}
Комментирование 1 позволяет завершить поток io_context, а снятие комментариев останавливает выход из потока io_context.
@liliscent, сэр, я понимаю вашу точку зрения, но я считаю, что асинхронный ввод-вывод в сокете более удобен, чем синхронная модель. Я также пытаюсь получить практический опыт работы с моделью асинхронного ввода-вывода, прежде чем мое приложение будет масштабировано на несколько устройств.
Если вы хотите использовать поток для поддержания состояния одного соединения, тогда вам в первую очередь не нужен async io, для этого и предназначен блокированный io. В async io поток предназначен только для выполнения операции io, он одновременно содержит несколько состояний подключения.