При вводе некорректного ip-адреса или номера порта, модуль кода, использующий boost::asio уходит в блок перманентно.
Простой пример кода:
int main(int argc, char* argv[]){
namespace ba = boost::asio;
using ba::ip::tcp;
ba::io_service service;
tcp::socket s(service);
if (argc<3)
return 255;
try {
auto it = tcp::resolver(service).resolve({argv[1], argv[2]});
s.connect(*it); // first resolved value
std::cout << "Connected " << s.local_endpoint() << " -> " << s.remote_endpoint() << "\n";
// demo write
ba::write(s, ba::buffer("hello world\n"));
} catch (const boost::system::system_error& e) {
std::cout << "ERROR:" << e.what() << "\n";
}}
Проблем не возникает, если заранее известно, что по адресу, который мы подали в программу, находится валидный и вполне себе жизнеспособный хост. К примеру, если ввести "127.0.0.1" или "192.168.10.17"(адрес одной из домашних машин) то программа отработает корректно и выведет заветное "Connected". Однако если ввести адрес вроде "1.2.3.4" или "12.13.14.15", "107.210.211.97" то на моменте
s.connect(*it); // first resolved value
Весь поток выполнения блокируется. Перманентно. Завершить программу можно только с помощью ручного завершения процесса.
Более комплексный пример:
boost::asio::io_context io_context;
boost::asio::ip::tcp::resolver resolver(io_context);
boost::asio::ip::tcp::resolver::results_type endpoints;
std::string address = ui->lineEdit_primaryServerAddress->text().toStdString();
endpoints = resolver.resolve(address, INET_SERVICE);
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.load_verify_file(SSL_CERT);
rb_baseClient c(io_context, ctx, endpoints);
c.set_request(CLNT_MSG_WHO_ARE_YOU);
try
{
boost::system::error_code _ec2;
io_context.run();
}
catch (std::exception& e)
{
io_context.stop();
std::cerr << e.what() << std::endl;
ui->label_primaryServerHostname->setStyleSheet("color: darkred");
this->pServerIsAlive = false;
emit pServerStatusChanged(false);
}
std::string reply=c.get_reply();
Это часть кода для клиента одного из проектов. Программа должна подсоединится по полученному из gui адресу к хосту, проверить валидность по, установленного на том конце, и в зависимости от реплая определить дальнейшие элементы граф. интерфейса. Если адрес корректный, то все работает так, как задумано. Однако если ввести некорректный адрес, к примеру, тот же "1.2.3.4" или десятичное число, к примеру, "1" или "15212", то поток выполнения уходит в блокирующий режим на моменте
io_context.run();
Отдебажить io_context.run(); не предоставляется возможным.
IO context наполняется в классе клиента. Вот его вырезка:
rb_baseClient::rb_baseClient(boost::asio::io_context& io_context, boost::asio::ssl::context& context,
boost::asio::ip::tcp::resolver::results_type endpoints) :
_socket(io_context, context), _endpoints(endpoints)
{
// memset(_reply, 0, max_length);
// memset(_request, 0, max_length);
this->connect();
}
void rb_baseClient::connect()
{
try
{
_socket.set_verify_mode(boost::asio::ssl::verify_peer);
_socket.set_verify_callback(
boost::bind(&rb_baseClient::verify_certificate, this, _1, _2));
boost::asio::async_connect(_socket.lowest_layer(), _endpoints,
boost::bind(&rb_baseClient::handle_connect, this,
boost::asio::placeholders::error));
}
catch (std::exception& e)
{
cerr << "rb_baseClient::connect: " << e.what();
strcpy(_reply, SERVER_CONNECTION_FAILED);
}
}
Обращался к официальной документации boost, но не смог найти там решение этой проблемы. Пытался также добавлять deadline-timers - но это оказалось бесполезным. Google и Yandex не помогли тоже.