Использование boost::asio::async_read не работает, но boost::asio::read работает (использую io_stream.run_one())

У меня есть собственный сокет posix, который я пытаюсь асинхронно прочитать с помощью boost::asio::async_read. Однако, когда я делаю это:

// io_stream and fd are passed by reference to this function
asio::posix::stream_descriptor stream(io_stream);
stream.assign(fd);

boost::system::error_code ec;

asio::async_read(stream, buffer,
                 asio::transfer_at_least(1),
                 boost::bind(doRead,
                             asio::placeholders::error,
                             asio::placeholders::bytes_transferred));
size_t count = io_service.run_one(ec);

Для переменной count установлено значение 0, обработчик doRead никогда не вызывается, а ec не содержит ошибок. Однако, если я заменю асинхронное чтение синхронным чтением:

size_t count = asio::read(stream, buffer,
                          asio::transfer_at_least(1));

Это работает, и я возвращаю ожидаемое количество данных обратно в переменную count.

Мои тестовые примеры с использованием fd, созданного "int pipe(int pipefd[2]);" и передача данных через это отлично работает с asio::async_read, поэтому я думаю, что это может быть несколько вариантов:

  • Каким-то образом родной дескриптор, который я передаю, каким-то образом не совместим с async_read, поэтому он молча терпит неудачу. Я пытался создать его с включенной и выключенной блокировкой, но безрезультатно.
  • io_service и posix::stream_descriptor каким-то образом не связаны, поэтому io_service никогда не пытается выполнить чтение. Может ли это быть связано с тем, что я передаю io_service по ссылке? (И если на то пошло, в пределах пары потоков?)

person Rory Hart    schedule 09.12.2011    source источник
comment
stream_descriptor отлично работает с дескриптором из конца чтения pipe, см. этот ответ. Я подозреваю, что ваша вторая пуля является причиной поведения, которое вы видите. Пожалуйста, отредактируйте свой вопрос и включите короткий, автономный, правильный пример для анализа.   -  person Sam Miller    schedule 09.12.2011
comment
Я соберу один в понедельник на работе, так как у меня дома нет кода, спасибо!   -  person Rory Hart    schedule 10.12.2011


Ответы (1)


Я нашел проблему.

Я вызывал io_service.stop() в функции инициализации объекта-владельца, поскольку его можно повторно инициализировать. Однако я не вызывал io_service.reset() после вызова остановки, и io_service не будет работать после остановки до тех пор, пока не будет вызван сброс.

Урок по RTFM как для остановки, так и для сброса документирует это.

Однако переменная boost::system::error_code не отражала это состояние, что немного расстраивает, поскольку избавило бы меня от возни.

person Rory Hart    schedule 12.12.2011