Как работает асинхронный пинг из примера Boost.Asio?

Взял отсюда пример выполнения пинга по типу стандартной команды в Linux. Не могу в этом коде понять одно:

Как видно, код зациклен через вызов двух обработчиков, один из которых вызывается через таймер. Обработчики, в свою очередь, вызывают метод, асинхронно (отложенно) вызывающий этот обработчик.

К тому как работает цикл start_receive + handle_receive вопросов нет, все понятно. Проблема в том, что внутри handle_receive должна произойти отмена вызова handle_timeout через таймер. А значит, в свою очередь, не должен быть повторно запущен start_send. Вызов timer_.cancel(); точно происходит (проверял).

Получается, что цикл start_send + handle_timeout должен разорваться при первом же получнном ответе. Но этого не происходит (код запускал). И я не могу понять почему. Как так получается?


Ответы (2 шт):

Автор решения: user7860670

Этот пример составлен неправильно. Функция обратного вызова для передачи в ::boost::asio::basic_waitable_timer::async_wait обязана принимать один аргумент с типом ::boost::system::error_code const &. При вызове timer_.cancel(); в этот обработчик будет передан boost::asio::error::operation_aborted в качестве кода ошибки. Обработчик обязан проверить код перед обработкой и не продолжать в случае получения ошибки.

→ Ссылка
Автор решения: eri
timer_.async_wait(boost::bind(&pinger::start_send, this));

async_wait ждет любого события на таймере. Tут нет обработки operation_aborted или expired - это задача колбэка (void on_timeout в доках), который запускает start_send в любом случае.

→ Ссылка