Название: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 05, 2009, 17:59 Доброго всем всего!
Вот тут : http://forum.vingrad.ru/forum/topic-268430/kw-qiodevice.html я пытался узнать, как же формируется сигнал readyRead() при приходе данных в сокет, но мне так никто ничего толком и не рассказал. Имеется ввиду то, что например когда мы создаем сокет и коннектимся к его сигналу readyRead() - у меня возникает вопрос: а каким образом этот сигнал выдается??? Ведь (если рассматривать к примеру Вин сокеты) для отлова событий от сокета необходимо использовать API функцию select (или WSASelect) . Если посмортеть исходники, то видно, что эту функцию запускает метод класса QAbstractSocket::waitForReadyRead(msecs) - НО ФИШКА В ТОМ, ЧТО мы то не вызываем этот метод! И при этом успешно отлавливаем сигнал readyRead() Поэтому вопрос: кто/что/какая функция выдает нам сигнал readyRead() ??? Я запутался в исходниках.. уже не могу понять ничего Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: Авварон от Август 05, 2009, 18:03 ищи emit readyRead() по идее она должна стоять после селекта
Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: Alex Custov от Август 05, 2009, 18:35 Поэтому вопрос: кто/что/какая функция выдает нам сигнал readyRead() ??? По событию на сокете вызывается метод Цитировать bool QAbstractSocketPrivate::canReadNotification() { ... if (!emittedReadyRead && hasData) { emittedReadyRead = true; emit q->readyRead(); emittedReadyRead = false; } ... } Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 05, 2009, 18:39 select отрабытывет в цикле обработки событий.
Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 05, 2009, 18:54 Цитировать По событию на сокете вызывается метод Цитировать bool QAbstractSocketPrivate::canReadNotification() ..... да, это все так.... метод canReadNotification() вызывается например тут: Код: bool QAbstractSocket::waitForReadyRead(int msecs) Цитировать select отрабытывет в цикле обработки событий. где это реализовано в коде? а? :)Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 05, 2009, 18:59 где это реализовано в коде? а? :) /src/corelib/kernel/qeventdispatcher_unix.cppфункция doSelect. Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 05, 2009, 19:08 блина, сложно то как!
А если я хочу сделать к примеру аналогично сокету - но для последовательного порта, то что я должен сделать, чтобы при создании класса последовательного порта - в цикле сообщений стало вызываться select (для UNIX) или waitForSingleObject (для Windows) ? Например в классе последовательного порта реализован метод waitForReadyRead(msecs) c использованием этих ядерных функций : select и waitForSingleObject + к тому класс последовательного порта является наследником от QIODevice - НО я хочу сделать так, чтобы сигнал readyRead() емиттился сам при создании класса! А не только при вызове waitForReadyRead()! Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 05, 2009, 19:12 блина, сложно то как! Под linux ничего делать не надо, подсовываешь в QSocketNotifier дескриптор открытого последовательного порта и все будет работать.А если я хочу сделать к примеру аналогично сокету - но для последовательного порта, то что я должен сделать, чтобы при создании класса последовательного порта - в цикле сообщений стало вызываться select (для UNIX) или waitForSingleObject (для Windows) ? Например в классе последовательного порта реализован метод waitForReadyRead(msecs) c использованием этих ядерных функций : select и waitForSingleObject + к тому класс последовательного порта является наследником от QIODevice - НО я хочу сделать так, чтобы сигнал readyRead() емиттился сам при создании класса! А не только при вызове waitForReadyRead()! С вендой помочь не могу... Хотя можно попробовать периодически вызывать waitForSingleObject (по таймеру например) и при необходимости генерировать сигнал. Реализация QSocketNotifier не так уж и сложна. При создании объекта, он регистрируется в глобальном списке. Далее в цикле обработки событий проверяются все зарегистрированные дескрипторы и для тех которые сработали, вызывается сигнал. Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 05, 2009, 19:33 Цитировать Под linux ничего делать не надо, подсовываешь в QSocketNotifier дескриптор открытого последовательного порта и все будет работать. а поподробнее пжлста! Куда и что подсовывать конкретно? Лучше примерчик! Цитировать С вендой помочь не могу... ну там не только waitForSingleObject нужен.. там целая цепочка функцийХотя можно попробовать периодически вызывать waitForSingleObject (по таймеру например) и при необходимости генерировать сигнал. Цитировать Реализация QSocketNotifier не так уж и сложна. При создании объекта, он регистрируется в глобальном списке. Далее в цикле обработки событий проверяются все зарегистрированные дескрипторы и для тех которые сработали, вызывается сигнал. для меня это непонятно :(Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 05, 2009, 19:42 а поподробнее пжлста! Куда и что подсовывать конкретно? Лучше примерчик! Код
Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 05, 2009, 19:58 Цитировать .... connect( readNotifier, SIGNAL( activated( int ) ), ... ); .... т.е. далее мне нужно в таком случае написать что-то подобное: Код: int fd = ::open( "/dev/ttyS0", O_RDWR | O_NONBLOCK | O_NOCTTY ); , где this - это мой класс "последовательный порт" , ккоторый имеет сигнал readyRead() ? а удалять объект *readNotifier нужно ? Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 05, 2009, 20:01 т.е. далее мне нужно в таком случае написать что-то подобное: Да. И добавить this в конструктор:Код: int fd = ::open( "/dev/ttyS0", O_RDWR | O_NONBLOCK | O_NOCTTY ); Код
Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 05, 2009, 20:09 ааааа!!! спасибо огромное! щас буду пробовать! Все кажется теперь таким простым... :)
А вот все-таки теперь с виндус проблема остается... ( Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 05, 2009, 20:21 А вот все-таки теперь с виндус проблема остается... ( Посмотрел я реализацию у тебя в QSerialDevice.В примитиве, если по таймеру вызывать waitForReadyRead( 0, true ), то получим похожий функционал.... Дальше подумай как это лучше организовать. ;) Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: Alex Custov от Август 05, 2009, 21:05 НО! кто вызывает waitForReadyRead(msecs) ????? :) При чём тут вообще waitForReadyRead() ? ;D Ещё раз - по событию на сокете вызывается метод canReadNotification(), который и эмитит сигнал. Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: ритт от Август 06, 2009, 01:21 возможно, поможет
QWinEventNotifier(HANDLE hEvent, QObject *parent = 0) QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier); Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 06, 2009, 07:57 2 Константин, спасибо за наводку,
я так понимаю, что в качестве дескриптора события в класс QWinEventNotifier(HANDLE hEvent, QObject *parent = 0), в данном случае можно подставить дескриптор ovl.hEvent (см. код ниже), но! событие о приходе байт в порт формируется не только от ovl.hEvent, но и в ходе анализа переменной eventMask : Код: .... Код: .... тут как-то не пойму как подступиться к этому , но есть мысль: написать в классе "последовательный порт" отдельный метод, используя за базу код, приведеннный выше (с небольшими изменениями) , и вызывать этот новый метод при открытии последовательного порта... ЗЫ: а каким образом при вставке кода можно сделать подсветку С++ ? какие тэги нужны? Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 06, 2009, 09:56 такс,
1 . просмотрел исходники QWinEventNotifier: Код: QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent) и я так понял, что специально вызывать QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier) не нужно, т.к. оно уже вызвается в конструкторе 2. Используя QWinEventNotifier - я смогу отловить только факт срабатывания события ! Но узнать что это за событие я не смогу, т.к. для анализа необходимо проверять значения функции Win API - WaitForSingleObject ! 3. ИЛИ же проверять переменную eventMask , значение которой возвратила ф-я Win API WaitCommEvent(hd, &eventMask, &ovl) Такс, теперь бы сделать как-то анализ п.2 и п.3 ... буду думать :) 4. И еще не понятен один момент, как же QSocketNotifier обрабатывает события по типам Read, Write, Exeption ? Ведь в исходниках QSocketNotifier ему в конструктор передается тип (Type type) НО! НИГДЕ ДАЛЬШЕ ОН НЕ ОБРАБАТЫВАЕТСЯ, а просто присваивается приватной переменной sntype .... В общем вопросов больше чем ответов :( Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 06, 2009, 10:10 2. Используя QWinEventNotifier - я смогу отловить только факт срабатывания события ! Но узнать что это за событие я не смогу, т.к. для анализа необходимо проверять значения функции Win API - WaitForSingleObject ! В конструкторе QWinEventNotifier ты передаешь хендл своего события, которое будет ждать этот нотификатор (будет вызываться WaitForSingleObject для этого события) и как только это событие произойдет, будет послан сигнал activated( HANDLE ) с хендлом этого события.Т.е. тебе нужно создать и настроить событие, а Qt будет проверять его и сообщит тебе, когда оно произошло. Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 06, 2009, 10:17 Цитировать В конструкторе QWinEventNotifier ты передаешь хендл своего события, которое будет ждать этот нотификатор (будет вызываться WaitForSingleObject для этого события) и как только это событие произойдет, будет послан сигнал activated( HANDLE ) с хендлом этого события. дык тут WaitForSingleObject возвратить может или WAIT_OBJECT_0 или WAIT_TIMEOUT , а нужное мне событие - это WAIT_OBJECT_0 ! Но я не узнаю что это.. таймаут или пришли данные! :)Т.е. тебе нужно создать и настроить событие, а Qt будет проверять его и сообщит тебе, когда оно произошло. упс сорри, глянул в исходники, и там идет проверка на WAIT_OBJECT_0 Код: void QEventDispatcherWin32::activateEventNotifiers() Тут в принципе теперь все вроде понятно, но остается вопрос с отловом события через : Код: if (WaitCommEvent(hd, &eventMask, &ovl) == 0) { Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 06, 2009, 10:20 дык тут WaitForSingleObject возвратить может или WAIT_OBJECT_0 или WAIT_TIMEOUT , а нужное мне событие - это WAIT_OBJECT_0 , поэтому QWinEventNotifier при приходе данных в порт ИЛИ при таимауте возвратит это событие! Но я не узнаю что это.. таймаут или все пучком! :) WaitForSingleObject вызывается без блокировки (ожидания), т.е. тайм-аута быть не может.Поэтому он вызывается в цикле обработки событий, т.е. постоянно. Вызвали - события нет, пошли дальше, вызвали - событие произошло, сообщили об этом, пошли дальше.... Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 06, 2009, 10:32 Тут в принципе теперь все вроде понятно, но остается вопрос с отловом события через : А может быть или так или так? Забавно. ;)Код: if (WaitCommEvent(hd, &eventMask, &ovl) == 0) { Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 06, 2009, 10:43 Цитировать А может быть или так или так? Забавно. Подмигивающий аха! :)http://www.vsokovikov.narod.ru/New_MSDN_API/Comm_res/fn_waitcommevent.htm Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: BRE от Август 06, 2009, 11:11 Цитировать А может быть или так или так? Забавно. Подмигивающий аха! :)http://www.vsokovikov.narod.ru/New_MSDN_API/Comm_res/fn_waitcommevent.htm Хмм. Как все не просто. Тогда нужно постоянно вызывать WaitCommEvent для проверки.... [off]Почитал доку по нескольким функциям и нахлынуло, как же Микрософт любит все усложнить... ;)[/off] Название: Re: Принцип формирования сигналов на примере QTcpSocket Отправлено: kuzulis от Август 07, 2009, 14:39 такс, немного поразбирался с текущей реализацией в QT событий, и решил создавать СВОИ события при работе с последовательным портом !
просмотрел класс QEvent и однаружил там это: QEvent::User, т.е. я хочу например создать свое(юзер-определяемое) событие при работе порта, аналогичное QEvent::SockAct , т.к. QSocketNotifier не отвечает поставленным требованиям в полной мере, т.е. работает только для POSIX ОС! Я хочу сделать что то типа QSerialNotifier который бы охватывал и POSIX и WIN32 ОС! Очень уж хочется создать класс для работы с последовательным устройством по всем принципам QT (т.е. аналогично QAbstractSocket и т.п.) !!! Помогите пожалуйста знатоки определится с чего начать :) Исходные данные: 1. Для POSIX для отлова событий от порта используется ::select (тут в принципе QSocketNotifier годится) 2. Для Виндовс для отлова событий от порта необходимо использовать WaitCommEvent в связке с WaitForSingleObject. (тут можно пошаманить с QWinEventNotifier ) Хочу: 1. Создать какой-то общий класс, аналогичный QSocketNotifier и QWinEventNotifier который бы отражал всю глубину глубин (я сам не знаю что) В принципе я смог бы (для тестирования хотябы в линуксе) использовать QSocketNotifier - но тогда возникает вопрос : КАК ПРАВИЛЛЬНО РЕАЛИЗОВАТЬ тогда метод waitForReadyRead(msecs) и waitForBytesWritten(msecs) c учетом того, что эти методы должны зависят и от QSocketNotifier !!!! т.е. короче аналогично тому как в QAbstractSocket сделано - чтобы и события "правильно" в петле обрабатывалить и "правильно" работали методы waitForReadyRead и т.п. ЗЫ: извиняюсь за сумбур.. я еще не представляю четко то что нужно.. |