[boost::asio]прерывание async_read обработчиком таймера
От: kvser  
Дата: 18.05.09 12:43
Оценка:
Здравствуйте!

Изучаю boost::asio.
Пример (все async операции для одного io_service.run):


void timerHandler(const boost::system::error_code& error)
{
  if (!error)
  {
    //запись в socket
  }
}

void readHandler(const boost::system::error_code& e, std::size_t bytes_transferred)
{
  if (!e)
  {
    //прочитали данные размером длины буфера, выполняем к примеру запись ответа
  }
}

//ожидаем таймер
timer.async_wait(timerHandler);
...
boost::asio::async_read(socket,    boost::asio::buffer(buffer), readHandler); // читаем пока буфер не заполниться


Необходимо при отсутствии данных в течение некоторого времени записать в socket тестовую посылку. Может быть следующая последовательность событий:
1) прочитали часть посылки
2) сработал таймер ???
Каким образом можно избежать данной последовательности?
Данная последовательность не должна появляться, потому как после чтения чего-либо из socket, таймер должен остановиться и после получения всей посылки запуститься.

Думаю что надо использовать вариант async_read для чтения с условием, а в обработчике проверки условия после первого байта останавливать таймер, а после последнего запускать

19.05.09 08:06: Перенесено из 'Средства разработки'
Re: [boost::asio]прерывание async_read обработчиком таймера
От: Vinick Россия  
Дата: 19.05.09 22:25
Оценка:
Здравствуйте, kvser, Вы писали:

K>Необходимо при отсутствии данных в течение некоторого времени записать в socket тестовую посылку. Может быть следующая последовательность событий:

K>1) прочитали часть посылки
K>2) сработал таймер ???
K>Каким образом можно избежать данной последовательности?
K>Данная последовательность не должна появляться, потому как после чтения чего-либо из socket, таймер должен остановиться и после получения всей посылки запуститься.

Не совсем понятно что означает "посылка". Это какая-то структура переменной длины или фиксированный массив байт?
async_read вызовет хендлер только при полном заполнении буффера или при ошибке. Если посылка целиком умещается в буфер, то такая ситуация невозможна, при условии что io_service::run() запущен в одном потоке.

K>Думаю что надо использовать вариант async_read для чтения с условием, а в обработчике проверки условия после первого байта останавливать таймер, а после последнего запускать


Получите первый байт, остановите таймер, после этого произойдет задержка и следующий байт получите только через 10 часов, а таймер то выключен
Re[2]: [boost::asio]прерывание async_read обработчиком тайме
От: kvser  
Дата: 20.05.09 04:18
Оценка:
Здравствуйте, Vinick, Вы писали:

K>>Необходимо при отсутствии данных в течение некоторого времени записать в socket тестовую посылку. Может быть следующая последовательность событий:

K>>1) прочитали часть посылки
K>>2) сработал таймер ???

V>Не совсем понятно что означает "посылка". Это какая-то структура переменной длины или фиксированный массив байт?


псылка/сообщение/и т.д. в данном контексте означает последовательность байт фиксированной длины, которая читается в буфер соответствующего размера

V>async_read вызовет хендлер только при полном заполнении буффера или при ошибке. Если посылка целиком умещается в буфер, то такая ситуация невозможна, при условии что io_service::run() запущен в одном потоке.


Вы хотите сказать что, если началось чтение, то хандлер таймера не вызовется пока не заполниться весь буфер? но это же не так

K>>Думаю что надо использовать вариант async_read для чтения с условием, а в обработчике проверки условия после первого байта останавливать таймер, а после последнего запускать

V>Получите первый байт, остановите таймер, после этого произойдет задержка и следующий байт получите только через 10 часов, а таймер то выключен

неее, за это отвечает другой таймер, назовем его t2
а про таймер который я говорю(назовем его t3), работает для того чтобы, если не было никаких сообщений некоторое время, то послать сообщение проверки связи
Re[3]: [boost::asio]прерывание async_read обработчиком тайме
От: Vinick Россия  
Дата: 20.05.09 08:58
Оценка:
Здравствуйте, kvser, Вы писали:

K>Здравствуйте, Vinick, Вы писали:


K>>>Необходимо при отсутствии данных в течение некоторого времени записать в socket тестовую посылку. Может быть следующая последовательность событий:

K>>>1) прочитали часть посылки
K>>>2) сработал таймер ???

K>Вы хотите сказать что, если началось чтение, то хандлер таймера не вызовется пока не заполниться весь буфер? но это же не так


Я хочу сказать что при использовании async_read и при условии что размер буфера точно равен размеру сообщения, нет понятий "началось чтение" и "принята часть сообщения". В этом случае для приложения чтение происходит мгновенно в момент вызова readHandler,все остальное скрыто в библиотеке.
Если таймер сбрасывать и снова взводить в readHandler, то можно отследить таймаут между приемом двух сообщений.
Если async_read заменить async_read_some (в этом случае придется самостоятельно буферизовать и разделять сообщения),и перед вызовом async_wait устанавливать какой-нибудь флаг, в readHandler этот флаг сбрасывать, а в timerHandler проверять состояние флага, то можно детектировать отсутствие данных на сокете в течении определенного времени.


K>неее, за это отвечает другой таймер, назовем его t2

K>а про таймер который я говорю(назовем его t3), работает для того чтобы, если не было никаких сообщений некоторое время, то послать сообщение проверки связи

А так ли нужны такие сложности. Может достаточно проверять просто отсутствие данных на сокете в течении определенного времени, безотносительно целое сообщение или его часть.
Re[4]: [boost::asio]прерывание async_read обработчиком тайме
От: kvser  
Дата: 20.05.09 09:15
Оценка:
Здравствуйте, Vinick, Вы писали:

V>Я хочу сказать что при использовании async_read и при условии что размер буфера точно равен размеру сообщения, нет понятий "началось чтение" и "принята часть сообщения". В этом случае для приложения чтение происходит мгновенно в момент вызова readHandler,все остальное скрыто в библиотеке.


вот меня и волновало как там в библиотеке, если я читаю 6 байт, а после чтения 4 сработает таймер, по которому данные записываются в сокет, то как поведет библиотека себя. Не надо ли предпринимать каких-либо дополнительных действий. получается что не надо

V>Если таймер сбрасывать и снова взводить в readHandler, то можно отследить таймаут между приемом двух сообщений.


K>>неее, за это отвечает другой таймер, назовем его t2

K>>а про таймер который я говорю(назовем его t3), работает для того чтобы, если не было никаких сообщений некоторое время, то послать сообщение проверки связи
V>А так ли нужны такие сложности. Может достаточно проверять просто отсутствие данных на сокете в течении определенного времени, безотносительно целое сообщение или его часть.

протокол такой, ГОСТ Р МЭК 60870-5-104
Re[5]: [boost::asio]прерывание async_read обработчиком тайме
От: kvser  
Дата: 20.05.09 10:01
Оценка:
Здравствуйте, Vinick, Вы писали:

K>А так ли нужны такие сложности. Может достаточно проверять просто отсутствие данных на сокете в течении определенного времени, безотносительно целое сообщение или его часть.


и был вопрос в том, что произойдет если только часть сообщения успеет обработаться async_read'ом. Подумывал о том, чтобы после получения хотя бы байта, перезапускать таймер t3, потому что если он сработает во время выполнения async_read, то надо писать в сокет и ждать ответа уже на это тестовое сообщение. Получается что при следующем чтении, ожидая ответ на тестовое сообщение, я начну получать из какого-то "библиотечного" буфера остаточные данные недополученного ранее сообщения, в результате неправильный ответ на тест и дисконнект.
А за время чтения отвечает другой таймер t2
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.