Я пытаюсь реализовать 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 ().
Какие изменения необходимы, чтобы сохранить пример кода?
Мои проблемы:
При звонке:
Start() {
socket_.async_connect(Handleconnect);
dealine_.async_wait(HandleTimeout);
}
HandleConnect()
может быть завершено в другой теме еще до async_wait()
(маловероятно, но возможно). Должен ли я strand
заворачивать Start()
, HandleConnect()
, а также HandleTimeout()
?
Что, если HandleConnect()
сначала вызывается без ошибок, но deadline_timer.cancel()
или же deadline_timer.expires_from_now()
не удается, потому что HandleTimeout()
«были в очереди на вызов в ближайшее время»? Похоже, пример кода позволяет HandleTimeout()
закрыть сокет. Такое поведение (таймер закрывает соединение после того, как мы успешно запустили некоторые операции после соединения) может легко привести к серьезной головной боли.
Что, если HandleTimeout()
а также socket.close()
называются первыми. Это возможно HandlerConnect()
быть уже «в очереди» без ошибок? Документация гласит: «Любые асинхронные операции отправки, получения или подключения будут немедленно отменены и завершатся с boost::asio::error::operation_aborted
ошибка «. Что означает» немедленно «в среде многопоточности?
Вам следует обернуть пряди каждого обработчика, если вы хотите предотвратить их параллельное выполнение в разных потоках. Я думаю, что некоторые обработчики завершения будут иметь доступ socket_
или таймер, так что вам обязательно придется завернуть Start()
с пряди, а также. Но разве не было бы намного проще использовать модель io_service-per-CPU, т.е. основывать свое приложение на io_service
бассейн? ИМХО, ты получишь много меньше головной боли
Да, это возможно. Почему это головная боль? Сокет закрывается из-за «ложного тайм-аута», и вы начинаете процедуру повторного подключения (или чего-либо еще) так же, как если бы он был закрыт из-за сбоя сети.
Да, это также возможно, но опять же, это не должно вызывать проблем для правильно разработанной программы: если в HandleConnect
если вы попытаетесь выполнить какую-либо операцию для закрытого сокета, вы получите соответствующую ошибку. В любом случае, когда вы пытаетесь отправить / получить данные, вы на самом деле не знаете текущее состояние сокета / сети.
Других решений пока нет …