День добрый!
Столкнулся с небольшой проблемой:
Использую ACE для работы с комп портом и тп.
.....
class CSerialHandler : public ACE_Event_Handler
{
public:
int handle_input(ACE_HANDLE fd)
{
g_soResponse.clear();
for (char ch = 0; oTTY.recv(&ch, 1) == 1; g_soResponse += ch ) {;}
ACE_HEX_DUMP ( ( LM_DEBUG, g_soResponse.c_str(), g_soResponse.length(), ACE_TEXT("Response: ")) );
return 0;
}
};
.........
ACE_TTY_IO oTTY;
ACE_DEV_Connector oConnector;
oConnector.connect(oTTY, ACE_DEV_Addr(ACE_TEXT("/dev/ttyS1")));
ACE_TTY_IO::Serial_Params oParams;
oParams.baudrate = 9600;
oParams.readtimeoutmsec = 1000;
oParams.paritymode = "NONE";
oParams.databits = 8;
oParams.stopbits = 1;
oTTY.control(ACE_TTY_IO::SETPARAMS, &oParams);
.......
Проблема следующего плана: когда "приходит" handle_input я пытаюсь за раз все вычитать — вроде все ок. но когда я все вычитал(я об этом же не знаю) на следующей итерации пытаюсь вычитать и попадаю на тайматут чтения и потом уже только понимаю что все вычитано.
Вопрос: как можно организовать работу что бы не попадать на таймаут чтения
А>Вопрос: как можно организовать работу что бы не попадать на таймаут чтения
Я использую примерно такую схему:
std::string response;
ACE_Time_Value delta( 0, 100 );
ACE_Time_Value sleeptm( 5 );
for( ACE_Countdown_Time time_left( &sleeptm );
sleeptm > ACE_Time_Value::zero; time_left.update() )
{
read( response, 1 );
if( is_full_message( response ) )
break;
}
Реализация метода read( std::string &, size_t ) думаю не нужно писать.
Ну а что касается is_full_message( const std::string & ),
то здесь уже нужно смотреть с каким устройством общаешься, но найти что-нибудь можно всегда...
Попутный вопрос: насколько я понял из кода, то все это дело работает под *nix-ами, а под Windows
кому-нибудь удавалось заставить реактор перехватывать уведомления о поступивших данных в COM порте
( ACE_TTY_IO => ACE_Reactor => ACE_Event_Handler::handle_input( ACE_HANDLE ) )?
Если да, то поделитесь опытом. У меня ничего не вышло ни на ACE_Select_Reactor, ни на ACE_WFMO_Reactor.
Что и не удивительно-то
I>Попутный вопрос: насколько я понял из кода, то все это дело работает под *nix-ами, а под Windows
I>кому-нибудь удавалось заставить реактор перехватывать уведомления о поступивших данных в COM порте
I>( ACE_TTY_IO => ACE_Reactor => ACE_Event_Handler::handle_input( ACE_HANDLE ) )?
I>Если да, то поделитесь опытом. У меня ничего не вышло ни на ACE_Select_Reactor, ни на ACE_WFMO_Reactor.
I>Что и не удивительно-то
ACE_Select_Reactor использует функцию select для демультиплексирования событий. под виндами эта функция не работает с
компортом, только с сокетами.
что касается ACE_WFMO_Reactor. помоему тоже не помошник, тк на сколько я знаю, что бы ждать события на компорту нужно вызывать WaitCommEvent что ли(точно не помню, мсдн под рукой нет) а в исходниках я не нашел такой функции, те ее вызов.
на
http://groups.google.ru/group/comp.soft-sys.ace вроде говорили тчо может помочь прорактор, но я не смог разобраться что и как. чую что тоже облом.
вообще мысль написать свою имплеминтацию реактора которая бы задействовала WaitCommEvent, но пока увы не хватает времени.
А>вообще мысль написать свою имплеминтацию реактора которая бы задействовала WaitCommEvent, но пока увы не хватает времени.
Есть решение с использованием WFMO реактора.
По следам:
http://groups.google.ru/group/comp.soft-sys.ace/browse_thread/thread/993f73d86c415387/22b1fbb0811cdc17?lnk=gst&q=WaitCommEvent#22b1fbb0811cdc17
Цитирую: "I had to open the serial port in overlapped mode, then create an event, then
do a WaitCommEvent with the newly created manual-reset event. Register a
handler with the wfmo reactor using the created event, and handle_signal
will be called. I got that far, but I think within the handler, the event
has to be reset, and I'm not sure if another WaitCommEvent is necessary"
Пока еще не проверял. Но звучит весьма убедительно...