Тайм-аут async_connect () с несколькими потоками, выполняющими io_service.run ()

Я пытаюсь реализовать async_connect () с таймаутом.

    async_connect_with_timeout(socket_type & s,
std::function<void(BoostAndCustomError const & error)> const & connect_handler,
time_type timeout);

Когда операция завершается connect_handler(error) называется с error с указанием результата операции (включая тайм-аут).

Я надеялся использовать код из пример тайм-аута 1.51. Самое большое отличие в том, что я использую несколько рабочих потоков, выполняющих io_service.run ().

Какие изменения необходимы, чтобы сохранить пример кода?

Мои проблемы:

  1. При звонке:

    Start() {
    socket_.async_connect(Handleconnect);
    dealine_.async_wait(HandleTimeout);
    }
    

    HandleConnect() может быть завершено в другой теме еще до async_wait() (маловероятно, но возможно). Должен ли я strand заворачивать Start(), HandleConnect(), а также HandleTimeout()?

  2. Что, если HandleConnect() сначала вызывается без ошибок, но deadline_timer.cancel() или же deadline_timer.expires_from_now() не удается, потому что HandleTimeout() «были в очереди на вызов в ближайшее время»? Похоже, пример кода позволяет HandleTimeout() закрыть сокет. Такое поведение (таймер закрывает соединение после того, как мы успешно запустили некоторые операции после соединения) может легко привести к серьезной головной боли.

  3. Что, если HandleTimeout() а также socket.close() называются первыми. Это возможно HandlerConnect() быть уже «в очереди» без ошибок? Документация гласит: «Любые асинхронные операции отправки, получения или подключения будут немедленно отменены и завершатся с boost::asio::error::operation_aborted ошибка «. Что означает» немедленно «в среде многопоточности?

0

Решение

  1. Вам следует обернуть пряди каждого обработчика, если вы хотите предотвратить их параллельное выполнение в разных потоках. Я думаю, что некоторые обработчики завершения будут иметь доступ socket_ или таймер, так что вам обязательно придется завернуть Start() с пряди, а также. Но разве не было бы намного проще использовать модель io_service-per-CPU, т.е. основывать свое приложение на io_service бассейн? ИМХО, ты получишь много меньше головной боли

  2. Да, это возможно. Почему это головная боль? Сокет закрывается из-за «ложного тайм-аута», и вы начинаете процедуру повторного подключения (или чего-либо еще) так же, как если бы он был закрыт из-за сбоя сети.

  3. Да, это также возможно, но опять же, это не должно вызывать проблем для правильно разработанной программы: если в HandleConnect если вы попытаетесь выполнить какую-либо операцию для закрытого сокета, вы получите соответствующую ошибку. В любом случае, когда вы пытаетесь отправить / получить данные, вы на самом деле не знаете текущее состояние сокета / сети.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector