Използването на 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));

Това работи и получавам очакваното количество данни обратно в променливата за броене.

Моите тестови случаи, използващи 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