Russian Qt Forum
Апрель 19, 2024, 00:29
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Вопросы новичков
>
Проектирование приложения
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Проектирование приложения (Прочитано 3410 раз)
PazDim
Гость
Проектирование приложения
«
:
Май 25, 2019, 17:51 »
Добрый день. Нужна помощь - не понимаю архитектуры приложений для QT. В книжке написано, что библиотека использует слоты и сигналы, мол это лучше, чем callback. Но что делать с программами, которые не предполагают использования сигналов? Сейчас стоит задача в работе по TCP - необходим автомат, который принимает данные, обрабатывает и отправляет ответ (просто бесконечный цикл, опрашивающий сокет и отправляющий в него данные). У QTcpSocket чтение данных выполняется через сигналы. Попробовал вынести его в отдельный поток (основной занят автоматом и выполняения event loop не предполагает) - сигнал Connected генерируется, ReadyRead вроде тоже, но не могу нормально писать - write приходится вызывать из основного потока, ругается. Плюнул, попробовал следующий код:
Код:
#include <QTcpSocket>
#include <QByteArray>
#include <QThread>
#include <QHostAddress>
#include <QDebug>
int main()
{
QTcpSocket socket;
socket.bind(1234);
/* Выполняем подключение */
socket.connectToHost(QHostAddress("192.168.0.5"), 1234);
while (socket.state() != QTcpSocket::SocketState::ConnectedState)
qDebug() << socket.state();
qDebug() << "Connected";
QByteArray buf;
while (true)
{
buf.clear();
buf.append(static_cast<char>(0x02));
qDebug() << socket.write(buf);
socket.flush();
QThread::sleep(1);
}
return 0;
}
Сокет постоянно находится в состоянии попытки соединения, то есть ему даже для соединения нужен Event Loop? Как уже писал, основной цикл не предполагает передачи управления QT, лепить в каждую итерацию обработку сигналов тоже не хочется. Помню, что когда-то получилось работать по сети без сигналов, но выглядело и работало очень криво. Если идея бесконечного цила неверная, то как правильно проектировать программу? Обычное консольное приложение, не думал что так голова будет болеть.
Записан
PazDim
Гость
Re: Проектирование приложения
«
Ответ #1 :
Май 25, 2019, 18:40 »
Заменить бесконечный цикл таймером в одну миллисекунду и лепить все в одном потоке - это правильно?
Записан
PazDim
Гость
Re: Проектирование приложения
«
Ответ #2 :
Май 26, 2019, 11:01 »
Блин, в таймере получается здоровенный автомат с кучей кейсов. Логика вроде "отправить запрос, подождать ответа, обработать, отправить следующий, подождать" на сигналы-слоты совсем не ложится. Пока вижу решение как добавление отдельного потока, который не будет иметь цикла событий и будет вызывать слоты других классов с помощью QMetaObject::invokeMethod. Это нормальный подход?
Записан
sergek
Гипер активный житель
Offline
Сообщений: 870
Мы должны приносить пользу людям.
Re: Проектирование приложения
«
Ответ #3 :
Май 26, 2019, 12:23 »
Если ваша программа только принимает данные и отправляет ответ, то вообще никакого цикла и таймера не нужно. И уж, конечно, не нужны потоки.
Создаете сокет, соединяете его сигнал readyRead со своим слотом, в котором обрабатываются полученные данные. В нем реализуете логику определения того, что нужные данные получены (по размеру или признакам начала/конца). Скорее всего, понадобится буфер, куда записываете полученные данные.
В этом слоте реализуете запись в сокет ответа после того, как все данные получите. Не забудьте эти данные из буфера удалить.
Потом сокет подключаете (connectToHost) к порту и все.
Записан
Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
PazDim
Гость
Re: Проектирование приложения
«
Ответ #4 :
Май 26, 2019, 13:24 »
Цитата: sergek от Май 26, 2019, 12:23
Если ваша программа только принимает данные и отправляет ответ, то вообще никакого цикла и таймера не нужно. И уж, конечно, не нужны потоки.
Создаете сокет, соединяете его сигнал readyRead со своим слотом, в котором обрабатываются полученные данные. В нем реализуете логику определения того, что нужные данные получены (по размеру или признакам начала/конца). Скорее всего, понадобится буфер, куда записываете полученные данные.
В этом слоте реализуете запись в сокет ответа после того, как все данные получите. Не забудьте эти данные из буфера удалить.
Потом сокет подключаете (connectToHost) к порту и все.
Не все алгоритмы ложатся на такую структуру.
Отправить команду А.
Подождать, пока не придет ответ Б.
Отправить команду В.
Подождать, пока не придет ответ Г.
Разделять их на разные слоты слишком сложно - иногда приходится ждать дополнительного условия. Нужно накручивать таймеры для таймаутов.
Записан
sergek
Гипер активный житель
Offline
Сообщений: 870
Мы должны приносить пользу людям.
Re: Проектирование приложения
«
Ответ #5 :
Май 26, 2019, 14:43 »
Из постановки следовало только то, что программ должна отвечать на поступающие данные.
Если требуются запросы с ожиданием ответа, то можно после запроса организовать ожидание в цикле обработки событий. Этот цикл должен завершаться по по вашему сигналу, испускаемому из слота после получения данных, ну и по заданному таймауту.
А запросы, как вы и писали, можно делать по таймеру.
Записан
Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3258
Re: Проектирование приложения
«
Ответ #6 :
Май 26, 2019, 16:58 »
Посмотрите на waitForConnected и waitForReadyRead
Записан
PazDim
Гость
Re: Проектирование приложения
«
Ответ #7 :
Май 26, 2019, 17:16 »
Буду привыкать к сигналам-слотам. Посмотрим, что из этого получится.
Записан
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3258
Re: Проектирование приложения
«
Ответ #8 :
Май 26, 2019, 20:23 »
Сигнал-слоты всегда можно завернуть в синхронку с помощью QFuture/QFutureInterface. Я так недавно делал с QNetworkAccessManager'ом - мне надо было сделать синхронную функцию "скачай файл и положи сюда". Сделал тред с эвентлупом и завернул в футуру метод: QFuture<bool> download(QUrl src, QString dst).
Записан
PazDim
Гость
Re: Проектирование приложения
«
Ответ #9 :
Май 26, 2019, 20:29 »
Спасибо, почитаю, что за звери. Пока остановился на таймерах и автоматах.
Записан
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...