Здравствуйте, Wody, Вы писали:
W>Вот такая ситуация. Есть http-клиент, который соединяется с сервером и получает пакет данных. На весь сеанс работы отводится 5 секунд. Если клиент не успевает за 5 сек. получить данные, он разрывает соединение. Проблема в том, что (редко) в случае когда соединение разрывается из-за таймаута, хендлер для чтения данных (OnRead(const error_code& err)) вызывается когда сокет уже закрыт, а в err код ошибки не operation_aborted (как следует из документации по asio), а 0, то есть ошибки-то и нет. Причем, в буффере для чтения действительно ответ сервера.
W>В связи с этим 2 вопроса.
W>1) Правильно ли я понимаю, что если данные уже пришли и находятся в буффере, хендлер удаляется из очереди io_service и даже после закрытия сокета будет вызван без ошибки?
W>2) Если это верно (то есть close() не гарантирует вызов хендлера с кодом ошибки operation_aborted), то как лучше решить эту проблему? Или так нормально: if(!err && skt_.is_open()) ?
Дело в том, что завершение асинхронной операции и вызов обработчика (completion handler) в proactor разделены. Второе случается после первого (причинно-следственная связь), но не одновременно. После завершения (по завершению) асинхронной операции completion handler помещается в очередь, из которой его забирает тот поток (thread), что выполняет метод asio::io_service::poll/poll_one/run/run_one.
В Вашем случае асинхронная операция завершилась до закрытия сокета (!). Но вот вызов completion handler происходит в тот момент, когда сокет уже закрыт. Что делать в этом случае, зависит от логики работы приложения.
if(!err && skt_.is_open())
Это м/б одним из подходящих вариантов.
Programs must be written for people to read, and only incidentally for machines to execute