Re: Чтение из закрытого сокета в boost.asio
От: abrarov Россия http://asio-samples.blogspot.com/
Дата: 27.07.11 08:44
Оценка: 3 (1)
Здравствуйте, 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
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.