Russian Qt Forum
Октябрь 01, 2024, 00:27 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Принцип формирования сигналов на примере QTcpSocket  (Прочитано 14853 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« : Август 05, 2009, 17:59 »

Доброго всем всего!

Вот тут : http://forum.vingrad.ru/forum/topic-268430/kw-qiodevice.html

я пытался узнать, как же формируется сигнал readyRead() при приходе данных в сокет, но мне так никто ничего толком и не рассказал.

Имеется ввиду то, что например когда мы создаем сокет и коннектимся к его сигналу readyRead() - у меня возникает вопрос: а каким образом этот сигнал выдается???

Ведь (если рассматривать к примеру Вин сокеты) для отлова событий от сокета необходимо использовать API функцию select (или WSASelect) . Если посмортеть исходники, то видно, что эту функцию запускает метод класса QAbstractSocket::waitForReadyRead(msecs) - НО ФИШКА В ТОМ, ЧТО мы то не вызываем этот метод! И при этом успешно отлавливаем сигнал readyRead()

Поэтому вопрос: кто/что/какая функция выдает нам сигнал  readyRead() Непонимающий Я запутался в исходниках.. уже не могу понять ничего
Записан

ArchLinux x86_64 / Win10 64 bit
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #1 : Август 05, 2009, 18:03 »

ищи emit readyRead() по идее она должна стоять после селекта
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #2 : Август 05, 2009, 18:35 »

Поэтому вопрос: кто/что/какая функция выдает нам сигнал  readyRead() Непонимающий

По событию на сокете вызывается метод

Цитировать
bool QAbstractSocketPrivate::canReadNotification()
{

    ...

    if (!emittedReadyRead && hasData) {
        emittedReadyRead = true;
        emit q->readyRead();
        emittedReadyRead = false;
    }

    ...

}
Записан
BRE
Гость
« Ответ #3 : Август 05, 2009, 18:39 »

select отрабытывет в цикле обработки событий.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #4 : Август 05, 2009, 18:54 »

Цитировать
По событию на сокете вызывается метод

Цитировать
bool QAbstractSocketPrivate::canReadNotification()
.....

да, это все так.... метод canReadNotification() вызывается например тут:
Код:
bool QAbstractSocket::waitForReadyRead(int msecs)
{
...
         if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(),
                                               qt_timeout_value(msecs, stopWatch.elapsed()))) {
            d->socketError = d->socketEngine->error();
            setErrorString(d->socketEngine->errorString());
#if defined (QABSTRACTSOCKET_DEBUG)
            qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)",
                   msecs, d->socketError, errorString().toLatin1().constData());
#endif
            emit error(d->socketError);
            if (d->socketError != SocketTimeoutError)
                close();
            return false;
        }

        if (readyToRead) {
            if (d->canReadNotification())
                return true;
        }

        if (readyToWrite)
            d->canWriteNotification();

        if (state() != ConnectedState)
            return false;
    }
    return false;
}
НО! кто вызывает waitForReadyRead(msecs) Непонимающий?? Улыбающийся

Цитировать
select отрабытывет в цикле обработки событий.
где это реализовано в коде? а?  Улыбающийся
« Последнее редактирование: Август 05, 2009, 18:59 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #5 : Август 05, 2009, 18:59 »

где это реализовано в коде? а?  Улыбающийся
/src/corelib/kernel/qeventdispatcher_unix.cpp
функция doSelect.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #6 : Август 05, 2009, 19:08 »

блина, сложно то как!

А если я хочу сделать к примеру аналогично сокету - но для последовательного порта, то что я должен сделать, чтобы при создании класса последовательного порта - в цикле сообщений стало вызываться select (для UNIX) или waitForSingleObject (для Windows) ?

Например в классе последовательного порта реализован метод waitForReadyRead(msecs) c использованием этих ядерных функций : select и waitForSingleObject + к тому класс последовательного порта является наследником от QIODevice - НО я хочу сделать так, чтобы сигнал readyRead() емиттился сам при создании класса! А не только при вызове waitForReadyRead()!
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #7 : Август 05, 2009, 19:12 »

блина, сложно то как!

А если я хочу сделать к примеру аналогично сокету - но для последовательного порта, то что я должен сделать, чтобы при создании класса последовательного порта - в цикле сообщений стало вызываться select (для UNIX) или waitForSingleObject (для Windows) ?

Например в классе последовательного порта реализован метод waitForReadyRead(msecs) c использованием этих ядерных функций : select и waitForSingleObject + к тому класс последовательного порта является наследником от QIODevice - НО я хочу сделать так, чтобы сигнал readyRead() емиттился сам при создании класса! А не только при вызове waitForReadyRead()!
Под linux ничего делать не надо, подсовываешь в QSocketNotifier дескриптор открытого последовательного порта и все будет работать.
С вендой помочь не могу...
Хотя можно попробовать периодически вызывать waitForSingleObject (по таймеру например) и при необходимости генерировать сигнал.
Реализация QSocketNotifier не так уж и сложна. При создании объекта, он регистрируется в глобальном списке. Далее в цикле обработки событий проверяются все зарегистрированные дескрипторы и для тех которые сработали, вызывается сигнал.
« Последнее редактирование: Август 05, 2009, 19:16 от BRE » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #8 : Август 05, 2009, 19:33 »

Цитировать
Под linux ничего делать не надо, подсовываешь в QSocketNotifier дескриптор открытого последовательного порта и все будет работать.

а поподробнее пжлста! Куда и что подсовывать конкретно? Лучше примерчик!

Цитировать
С вендой помочь не могу...
Хотя можно попробовать периодически вызывать waitForSingleObject (по таймеру например) и при необходимости генерировать сигнал.
ну там не только waitForSingleObject  нужен.. там целая цепочка функций

Цитировать
Реализация QSocketNotifier не так уж и сложна. При создании объекта, он регистрируется в глобальном списке. Далее в цикле обработки событий проверяются все зарегистрированные дескрипторы и для тех которые сработали, вызывается сигнал.
для меня это непонятно Грустный
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #9 : Август 05, 2009, 19:42 »

а поподробнее пжлста! Куда и что подсовывать конкретно? Лучше примерчик!
Код
C++ (Qt)
int fd = ::open( "/dev/ttyS0", O_RDWR | O_NONBLOCK | O_NOCTTY );
QSocketNotifier *readNotifier = new QSocketNotifier( fd, QSocketNotifier::Read );
connect( readNotifier, SIGNAL( activated( int ) ), ... );
 
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #10 : Август 05, 2009, 19:58 »

Цитировать
....
connect( readNotifier, SIGNAL( activated( int ) ), ... );
....

т.е. далее мне нужно в таком случае написать что-то подобное:
Код:
int fd = ::open( "/dev/ttyS0", O_RDWR | O_NONBLOCK | O_NOCTTY );
QSocketNotifier *readNotifier = new QSocketNotifier( fd, QSocketNotifier::Read );
connect( readNotifier, SIGNAL( activated( int ) , this, SIGNAL(readyRead() );

, где this - это мой класс "последовательный порт" , ккоторый имеет сигнал readyRead() ?

а удалять объект *readNotifier нужно ?
« Последнее редактирование: Август 05, 2009, 20:01 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #11 : Август 05, 2009, 20:01 »

т.е. далее мне нужно в таком случае написать что-то подобное:
Код:
int fd = ::open( "/dev/ttyS0", O_RDWR | O_NONBLOCK | O_NOCTTY );
QSocketNotifier *readNotifier = new QSocketNotifier( fd, QSocketNotifier::Read );
connect( readNotifier, SIGNAL( activated( int ) , this, SIGNAL(readyRead() );
, где this - это мой класс "последовательный порт" , ккоторый имеет сигнал readyRead() ?
Да. И добавить this в конструктор:
Код
C++ (Qt)
QSocketNotifier *readNotifier = new QSocketNotifier( fd, QSocketNotifier::Read, this );
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #12 : Август 05, 2009, 20:09 »

ааааа!!! спасибо огромное! щас буду пробовать!  Все кажется теперь таким простым... Улыбающийся

А вот все-таки теперь с виндус проблема остается...  (
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #13 : Август 05, 2009, 20:21 »

А вот все-таки теперь с виндус проблема остается...  (
Посмотрел я реализацию у тебя в QSerialDevice.
В примитиве, если по таймеру вызывать waitForReadyRead( 0, true ), то получим похожий функционал....
Дальше подумай как это лучше организовать.  Подмигивающий
« Последнее редактирование: Август 05, 2009, 20:54 от BRE » Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #14 : Август 05, 2009, 21:05 »

НО! кто вызывает waitForReadyRead(msecs) Непонимающий?? Улыбающийся

При чём тут вообще waitForReadyRead() ? Смеющийся Ещё раз - по событию на сокете вызывается метод canReadNotification(), который и эмитит сигнал.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.093 секунд. Запросов: 23.