Поиск:

Ответ в темуСоздание новой темы Создание опроса
> QIODevice & waitFor 
:(
    Опции темы
xbarmaglot
Дата 6.6.2013, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 28.8.2012

Репутация: нет
Всего: нет



Класс QIODevice работает асинхронно: есть write и слот readyRead.
Но, помимо этого, есть методы waitForBytesWritten и waitForReadyRead, которые позволяют сделать работу синхронной.
Как можно реализовать данный механизм на собственном объекте?

З.Ы. Идея в том, что есть TCP поток, через который передаются данные различного типа.
Это команды, которые ходят одну и другую сторону. На некоторые команды нужно отвечать, а на некоторые нет.
То есть некоторые синхронные, а некоторые асинхронные. С асинхронными все понятно, а вот с синхронными проблема.
Нужно на посланный запрос получить ответ, который может быть замешан с асинхронными ответами.

Как быть в данном случае ?

PM MAIL   Вверх
bsa
Дата 7.6.2013, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



xbarmaglot, я не очень понимаю, что тебя затрудняет? Данные в любом случае отправляются в том порядке, в каком ты записываешь. Если ты не будешь работать с классом из нескольких потоков, то проблем у тебя быть не должно. Тупо реагируй на сигнал readyRead. Если же тебе необходимо отправлять асинхронные данные, а периодически синхронно отвечать, то, опять же, проблем быть не должно. Другое дело, что если твой протокол подразумевает, что после синхронной команды не может придти ничего, кроме синхронного ответа, то проблема не в классе, а в протоколе.
PM   Вверх
xbarmaglot
Дата 7.6.2013, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 28.8.2012

Репутация: нет
Всего: нет



Цитата(bsa @  7.6.2013,  10:09 Найти цитируемый пост)
Другое дело, что если твой протокол подразумевает, что после синхронной команды не может придти ничего, кроме синхронного ответа, то проблема не в классе, а в протоколе. 

после синхронной команды может прийти не ответ на него, а асинхронные данные, например.

Просто со стороны сервера тоже могут идти асинхронные данные.
PM MAIL   Вверх
bsa
Дата 7.6.2013, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



xbarmaglot, в данный момент не очень понятно, что вызывает у тебя затруднения.
PM   Вверх
xbarmaglot
Дата 7.6.2013, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 28.8.2012

Репутация: нет
Всего: нет



Цитата(bsa @ 7.6.2013,  13:52)
xbarmaglot, в данный момент не очень понятно, что вызывает у тебя затруднения.

смысл в том, что клиент, подключаясь к серверу, может ему передавать как асинхронные данные, так и синхронные.
на синхронные он должен дождаться ответа с результатом. сложность в том, что сервер помимо ответов может сам слать асинхронные данные.
так вот получается, что когда клиент посылает синхронную команду, то в ответ может прийти не результат выполнения команды, а асинхронные данные. 
вот и возникает вопрос-как реализовать ожидание результата синхронного запроса?
PM MAIL   Вверх
Guinness
Дата 7.6.2013, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 21.6.2009
Где: Зеленоград

Репутация: 2
Всего: 10



А может Вам по другому протокол реализовать? Чтобы не было этой путаницы с синхронными и несинхронными данными?
А в readyRead обрабатывать данные по некоему идентификатору, который бы различал данные по их важности?
PM MAIL   Вверх
bsa
Дата 7.6.2013, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



xbarmaglot, все. Я понял тебя. Это очень легко решается (причем, более корректно, чем ты планировал) следующим образом: когда отправляешь синхронную команду, то ставишь флажок и код команды. Когда приходит на нее ответ обрабатываешь его, снимаешь флажок, отправляешь отложенные асинхронные команды. При отправке асинхронной команды ты проверяешь флажок, если взведен, то помещаешь в очередь отложенных, иначе сразу отправляешь. Обработка ответов вообще единообразна - по сигналу readyRead читаешь и нужным образом реагируешь.
PM   Вверх
xbarmaglot
Дата 7.6.2013, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 28.8.2012

Репутация: нет
Всего: нет



Цитата(Guinness @  7.6.2013,  14:23 Найти цитируемый пост)
А может Вам по другому протокол реализовать? Чтобы не было этой путаницы с синхронными и несинхронными данными?
А в readyRead обрабатывать данные по некоему идентификатору, который бы различал данные по их важности? 

у меня есть ID и тип пакета, по которому я могу понять запрос это или ответ.


Цитата(bsa @  7.6.2013,  14:55 Найти цитируемый пост)
xbarmaglot, все. Я понял тебя. Это очень легко решается (причем, более корректно, чем ты планировал) следующим образом: когда отправляешь синхронную команду, то ставишь флажок и код команды. Когда приходит на нее ответ обрабатываешь его, снимаешь флажок, отправляешь отложенные асинхронные команды. При отправке асинхронной команды ты проверяешь флажок, если взведен, то помещаешь в очередь отложенных, иначе сразу отправляешь.

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

Но проблема в том, что клиент и сервер не синхронизированы. Допустим клиент начинает синхронный запрос.
Он отправляет данные на сокет. И начинает ждать ответа.
Отправка - это просто копирование в буфер сокета как только он послал, то сервер, не зная этого (еще не получив запроса)
пуляет данные. А потом получает запрос на выполнение синхронной операции.
Получается, что клиент в ответ получит не результат выполнения, а асинхронные данные.

З.Ы. Вся сложность в том, что клиент работает не по принципу запрос-ответ, а в том, что сервер сам может инициировать 
передачу асинхронных данных. Правда инициатором синхронных запросов может быть только клиент.


Цитата(bsa @  7.6.2013,  14:55 Найти цитируемый пост)
Обработка ответов вообще единообразна - по сигналу readyRead читаешь и нужным образом реагируешь. 

Так чтение в другом методе. В чем тут синхронность ?

вот пример
Код

send_async()
{
    send_data(...)
}

send_sync()
{
    send_data();
    wait_result();
}


а раз посылаю данные в дном методе, а читаю в другом, то тут я и не могу понять как реализовать синхронную операцию.

Или я что-то не понял ?
PM MAIL   Вверх
bsa
Дата 7.6.2013, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



ты логику не понимаешь. надо делать программу event-based. Т.е. ты обрабатываешь события, а не ждешь данные.
т.е. ты пульнул данные серверу и делаешь все что угодно (не ждешь ответ). Когда сервер пришлет ответ, то у тебя возникнет событие onReadyRead(). Отлично, в его обработчике ты делаешь необходимые операции и опять возвращаешься к "все что угодно".

Просто современные gui-приложения в принципе очень сложно сделать синхронными (т.е. что-то сделал, ждешь результат, опять что-то сделал, ждешь результат... - не прокатит). Там после любой реакции на внешние раздражители (пользователь, таймеры, данные из сокетов или другие события) программа должна вернуть управление системе. В случае Qt надо просто завершить функцию-слот.
PM   Вверх
xbarmaglot
Дата 7.6.2013, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 28.8.2012

Репутация: нет
Всего: нет



bsa, я понимаю, что в идеале алгоритм должен быть полностью асинхронным. Тогда и проблем не будет.
Просто я не совсем понимаю как это сделать.

Например, сейчас логика следующая: в отдельном потоке выполняются как синхронные, так асинхронные команды.
Для асинхронных команд есть очередь ответов. Я просто после отправки ожидаю на очереди ответ.
Получается, что я все-равно пытаюсь сделать все методы синхронными.

Последовательность действий алгоритма должна быть четко последовательной. Если не проходит како-либо вызов,
то дальнейшее выполнение алгоритма бессмысленно.

Если же реагировать на события в слоте, то это очень сложно. Да и слот не может знать что делать с пакетом определенного типа.
Это может знать лишь объект, посылающий запрос.

Может тут нужно автомат строить ? Только как быть с таймаутами на выполнение операций алгоритма ?

Добавлено @ 21:26
P.S. Вот простой пример: пусть для реализации алгоритма необходимо последовательно выполнить 3 команды.
Если делать все синхронно, то
Код

QThread::run
{
    if (!func1()) return;
    if (!func2()) return;
    if (!func3()) return;
}


Если все делать асинхронно, то
Код

class Object
{
    void send_data();
    void readyRead()
    {
        if (data.type == 0)
        {
            send_data(1);
        }
        if (data.type == 1)
        {
            send_data(2);
        }
        if (data.type == 2)
        {
            send_data(3);
        }
    }
}


как-то так...
А если методов десятки?

Или как-то проще через слоты можно обработать ?

Это сообщение отредактировал(а) xbarmaglot - 7.6.2013, 21:28
PM MAIL   Вверх
Guinness
Дата 8.6.2013, 08:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 21.6.2009
Где: Зеленоград

Репутация: 2
Всего: 10



Цитата(xbarmaglot @  7.6.2013,  22:17 Найти цитируемый пост)
А если методов десятки?

Ну да, для этого паттерн State и предлагается.
Можно попробовать Ваш класс разбить на несколько состояниний таких как: AsyncState, SyncState1, SyncState2, SyncState3. В синхронных состояниях асинхронные запросы отправляются в очередь и никак не обрабатываются. Обрабатываются лишь синхронные запросы,  в случае успеха - переход в другое состояние.
Как только синхронные состояния выполнились, происходит переход в асинхронное состояние, в котором происходит разгребание накопившейся очереди.
PM MAIL   Вверх
xbarmaglot
Дата 8.6.2013, 09:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 28.8.2012

Репутация: нет
Всего: нет



Guinness, то есть автомат ?
Дело в том, что переходы у меня сейчас реализованы по таймауту.
То есть если я послал запрс и в течении определенного времени не получил ответа, то бросаю исключение.
Автомат должен тогда перейти в конечное состояние. Можно ли сделать переходы, зависимые от времени ?

P.S. Да и про сам автомат не совсем понял как реализовать.
Тут вроде описано http://doc.crossplatform.ru/qt/4.7.x/statemachine-api.html
Но в моем случае есть данные, например, 3 типов. Они могут отправляться и приниматься объектом.
При получении данных определенного типа происходит переход в определенное состояние.



PM MAIL   Вверх
Guinness
Дата 8.6.2013, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 21.6.2009
Где: Зеленоград

Репутация: 2
Всего: 10



Цитата(xbarmaglot @  8.6.2013,  10:28 Найти цитируемый пост)
то есть автомат ?

Да. Просто в паттернах проектирования его называют State.
Цитата(xbarmaglot @  8.6.2013,  10:28 Найти цитируемый пост)
То есть если я послал запрс и в течении определенного времени не получил ответа, то бросаю исключение.Автомат должен тогда перейти в конечное состояние. Можно ли сделать переходы, зависимые от времени ?

Конечно можно, timerEvent никто не отменял). Просто при переходе в другое состояние запускается таймер, если timerEvent происходит раньше, чем приходят данные, то происходит переход в ошибочное состояние, ну либо куда Вам необходимо.
Цитата(xbarmaglot @  8.6.2013,  10:28 Найти цитируемый пост)
P.S. Да и про сам автомат не совсем понял как реализовать.Тут вроде описано http://doc.crossplatform.ru/qt/4.7.x/statemachine-api.html

Почитайте у GoF паттерн State. Вроде понятно описан у них. А ссылочка у меня не открылась. Кстати, на msdn были какие-то статьи по statemachine.
Цитата(xbarmaglot @  8.6.2013,  10:28 Найти цитируемый пост)
Но в моем случае есть данные, например, 3 типов. Они могут отправляться и приниматься объектом.При получении данных определенного типа происходит переход в определенное состояние.

Попробуйте сначала нарисовать все состояния как кружочки и объединить их ребрами, написав на них условия перехода. Потом напишите интерфейс общий для всех классов состояний. Дальше уже дело техники.
Так просто мне маловато информации, чтобы представлять задачу)
PM MAIL   Вверх
xbarmaglot
Дата 8.6.2013, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 28.8.2012

Репутация: нет
Всего: нет



Цитата(Guinness @ 8.6.2013,  14:07)
Цитата(xbarmaglot @  8.6.2013,  10:28 Найти цитируемый пост)
то есть автомат ?

Да. Просто в паттернах проектирования его называют State.
Цитата(xbarmaglot @  8.6.2013,  10:28 Найти цитируемый пост)
То есть если я послал запрс и в течении определенного времени не получил ответа, то бросаю исключение.Автомат должен тогда перейти в конечное состояние. Можно ли сделать переходы, зависимые от времени ?

Конечно можно, timerEvent никто не отменял). Просто при переходе в другое состояние запускается таймер, если timerEvent происходит раньше, чем приходят данные, то происходит переход в ошибочное состояние, ну либо куда Вам необходимо.
Цитата(xbarmaglot @  8.6.2013,  10:28 Найти цитируемый пост)
P.S. Да и про сам автомат не совсем понял как реализовать.Тут вроде описано http://doc.crossplatform.ru/qt/4.7.x/statemachine-api.html

Почитайте у GoF паттерн State. Вроде понятно описан у них. А ссылочка у меня не открылась. Кстати, на msdn были какие-то статьи по statemachine.
Цитата(xbarmaglot @  8.6.2013,  10:28 Найти цитируемый пост)
Но в моем случае есть данные, например, 3 типов. Они могут отправляться и приниматься объектом.При получении данных определенного типа происходит переход в определенное состояние.

Попробуйте сначала нарисовать все состояния как кружочки и объединить их ребрами, написав на них условия перехода. Потом напишите интерфейс общий для всех классов состояний. Дальше уже дело техники.
Так просто мне маловато информации, чтобы представлять задачу)

Guinness, я так и думал, что малой кровью не обойдется... Будет время обязательно займусь автоматами. Но сейчас нужно, чтоб работало...


Цитата(bsa @  7.6.2013,  18:15 Найти цитируемый пост)
ты логику не понимаешь. надо делать программу event-based. Т.е. ты обрабатываешь события, а не ждешь данные.
т.е. ты пульнул данные серверу и делаешь все что угодно (не ждешь ответ). Когда сервер пришлет ответ, то у тебя возникнет событие onReadyRead(). Отлично, в его обработчике ты делаешь необходимые операции и опять возвращаешься к "все что угодно".

Вот есть синхронный метод
Код

bool MyClass::send_command( const QByteArray& request )
{
    QMutexLocker locker(&m_mutex);
    qint64 bytes = m_socket->write(request);
    if (!m_socket->waitForBytesWritten())
    {
        qCritical() << m_socket->errorString();
        return false;
    }
    Q_ASSERT(bytes == request.size());
    if (!m_socket->waitForReadyRead())
    {
        qCritical() << m_socket->errorString();
        return false;
    }

    QByteArray response = socket->readLine();
    Q_ASSERT(!response.isEmpty());
    return true;
}



то есть вызвав данный метод он либо завершится успешно, либо нет.
Но если отправка данных и прием в разных методах, то я не совсем понимаю как реализовать то, что я хочу...
PM MAIL   Вверх
bsa
Дата 10.6.2013, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



xbarmaglot, любая программа - это машина состояний. Вот только далеко не всегда их конечное количество. Не обязательно делать явный конечный автомат, можно сделать проще - при отправке запроса сохранять контекст обработки ответа в очереди. Когда приходит ответ, то ты смотришь, подходит ли он к тому контексту, что первый в очереди, если подходит, то передает его контексту. Если нет, то значит это что-то асинхронное.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.1807 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.