Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: MaxoBik от Август 03, 2015, 23:33



Название: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 03, 2015, 23:33
Доброго времени суток, есть консольное приложения не на QT и есть QT GUI приложения, которое запускает это консольное приложен. Так вот, между этими процессами нужно наладить обмен сообщениями и передачу из консольного приложения в GUI некоторой структуры данных - какую лучше всего схему IPC выбрать для этого?


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Bepec от Август 04, 2015, 02:01
Socket'ы. Все иные способы или нуждаются в дополнительном контроле, или же труднореализуемы.

PS во всяком случае, лучше и кроссплатформеннее метода я не видел.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 05:35
Доброго времени суток, есть консольное приложения не на QT и есть QT GUI приложения, которое запускает это консольное приложен. Так вот, между этими процессами нужно наладить обмен сообщениями и передачу из консольного приложения в GUI некоторой структуры данных - какую лучше всего схему IPC выбрать для этого?
Пайпы (pipe).


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: __Heaven__ от Август 04, 2015, 09:24
Может быть ещё QProcess заинтересует. Общается с программой через потоки ввода/вывода.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 09:38
Может быть ещё QProcess заинтересует. Общается с программой через потоки ввода/вывода.
Это и есть пайпы. :)


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: __Heaven__ от Август 04, 2015, 10:06
Упс. Извиняюсь за безграмотность :)


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: __Heaven__ от Август 04, 2015, 10:08
Хочу развить тему и узнать, а что из себя представляют сокеты? Википедия особо не помогла разобраться.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 10:22
Хочу развить тему и узнать, а что из себя представляют сокеты? Википедия особо не помогла разобраться.
Сетевые сокеты: QTcpSocket/QUdpSocket.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: __Heaven__ от Август 04, 2015, 10:41
Ааа. То есть подразумевается, что на одной машине будет происходить общение через 127.0.0.1...
Голосую за QProcess! :)

Кстати, я ещё наткнулся на метод разделения памяти. на сколько он хорош? Я так понял, что его преимущественно лучше использовать, если пишешь какой-то решатель, а в остальных случаях - QProcess. Или я ошибаюсь?


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Fregloin от Август 04, 2015, 11:15
есть еще QLocalSocket...


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 04, 2015, 11:43
Может быть ещё QProcess заинтересует. Общается с программой через потоки ввода/вывода.
Это и есть пайпы. :)
QProcess, насколько я понял использует только в Windows пайпы и только для записи в запускаемый процесс, а читает данные из stdout приложения, при таком раскладе как мне получить структуру данных из консольного приложения? Сериализировать/приводить ее в текст и выводить в stdout? Такое что-то мне не очень кажется.
есть еще QLocalSocket...
Тот же PIPE в Windows. Да я читал какие есть способы в IPC в QT, мне вот нужно понять, что выбрать и как меньшими усилиями это реализовать.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 12:13
QProcess, насколько я понял использует только в Windows
Нет, пайпы это понятие кроссплатформенное. И появились они на юниксе.

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

при таком раскладе как мне получить структуру данных из консольного приложения? Сериализировать/приводить ее в текст и выводить в stdout?
Зачем ее приводить в текст. Пайп это канал данных, вы туда можете писать что захотите.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 04, 2015, 13:07

Зачем ее приводить в текст. Пайп это канал данных, вы туда можете писать что захотите.

Ну а как еще? К примеру пайпы QProcess - я подключился к сигналу readyReadStandardOutput, в нем получаю readAllStandardOutput, но проблема в том как я буду определять что это строка или структура данных которую записали в stdout в консольном приложении через fwrite?


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 13:11
Ну а как еще? К примеру пайпы QProcess - я подключился к сигналу readyReadStandardOutput, в нем получаю readAllStandardOutput, но проблема в том как я буду определять что это строка или структура данных которую записали в stdout в консольном приложении через fwrite?
Для любого обмена между несколькими участниками нужен протокол этого общения. Вы можете передавать команды/запросы от GUI к бекэнду, а он будет возвращать вам результаты, хоть строками, хоть бинарными структурами.
Как вы придумаете протокол, согласно этого протокола и будете определять, что вам шлет бекэнд.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: __Heaven__ от Август 04, 2015, 13:17
Вы же заранее знаете в каком порядке у вас будут поступать данные? Вот и подставляйте их в соответствующие ячейки структуры. Главное при чтении не забывайте длину проверять.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 04, 2015, 13:18
Ну а как еще? К примеру пайпы QProcess - я подключился к сигналу readyReadStandardOutput, в нем получаю readAllStandardOutput, но проблема в том как я буду определять что это строка или структура данных которую записали в stdout в консольном приложении через fwrite?
Для любого обмена между несколькими участниками нужен протокол этого общения. Вы можете передавать команды/запросы от GUI к бекэнду, а он будет возвращать вам результаты, хоть строками, хоть бинарными структурами.
Как вы придумаете протокол, согласно этого протокола и будете определять, что вам шлет бекэнд.
Ну, грубо говоря это и есть сериализация данных.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: qate от Август 04, 2015, 13:19
ответ будет точнее, если будет известно что делает консольное приложение


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 13:21
Ну, грубо говоря это и есть сериализация данных.
Нет, серилизация это перевод данных из одного представления в другое.
Протокол это правила взаимодействия нескольких участников.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 04, 2015, 13:22
ответ будет точнее, если будет известно что делает консольное приложение

Это вообще не важно что оно делает, здесь разговор про обмен данными между двумя процессами.

Вы же заранее знаете в каком порядке у вас будут поступать данные? Вот и подставляйте их в соответствующие ячейки структуры. Главное при чтении не забывайте длину проверять.
Через это же пайпы будет идти и строки, ладно я понял направления, попробую через пайпы и свою кастомную сериализацию.
Всем СПАСИБО за подсказки.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Bepec от Август 04, 2015, 16:22
Я б всё же советовал socket'ы. Там меньше подводных камней и очень быстро можно организовать сетевое взаимодействие :)


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 20:08
Я б всё же советовал socket'ы. Там меньше подводных камней и очень быстро можно организовать сетевое взаимодействие :)
А какие подводные камни в пайпах?
Прямой канал данных, без дополнительного оверхеда, связанного с накручиванием/раскручиванием заголовков данных по всему сетевому стеку, который будет у сетевых сокетов. Я еще пойму локальные сокеты, но в венде их вроде нет (точно не знаю).


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 04, 2015, 22:00
В общем QProcess как PIPE в винде использовать нереально - нет возможности без кучи багов читать stdin в неблокирующем режиме, да у меня еще и в потоках это дело - вообще начинается дикие пляски. В nix все прекрасно работает через select, в виндовс дохлая затея. Придется QLocalSocket использовать.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 22:04
В общем QProcess как PIPE в винде использовать нереально - нет возможности без кучи багов читать stdin в неблокирующем режиме, да у меня еще и в потоках это дело - вообще начинается дикие пляски. В nix все прекрасно работает через select, в виндовс дохлая затея. Придется QLocalSocket использовать.
Если вы используете QProcess, то у него есть сигнал, о приходе новых данных.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 04, 2015, 22:11
Если вы используете QProcess, то у него есть сигнал, о приходе новых данных.
Да нет, с QT приложениям то все нормально, с консольным приложениям написаным на чистом С\С++, которое и запускает мой QT GUI клиент, проблемы со stdin-ом в виндовс, придется создавать поток, который будет читать stdin, добавлять ему синхронизацию и прочие и прочие мелочи. Нет возможности в виндовс нормально читать из stdin продолжительное время в неблокирующем режиме.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 22:15
Да нет, с QT приложениям то все нормально, с консольным приложениям написаным на чистом С\С++, которое и запускает мой QT GUI клиент, проблемы со stdin-ом в виндовс, придется создавать поток, который будет читать stdin, добавлять ему синхронизацию и прочие и прочие мелочи. Нет возможности в виндовс нормально читать из stdin продолжительное время в неблокирующем режиме.
Такие возможности есть, boost.process прекрасно это умеет.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 04, 2015, 22:31
Да нет, с QT приложениям то все нормально, с консольным приложениям написаным на чистом С\С++, которое и запускает мой QT GUI клиент, проблемы со stdin-ом в виндовс, придется создавать поток, который будет читать stdin, добавлять ему синхронизацию и прочие и прочие мелочи. Нет возможности в виндовс нормально читать из stdin продолжительное время в неблокирующем режиме.
Такие возможности есть, boost.process прекрасно это умеет.
Ну да, а сверху еще помазать Boost Asio, но мне тянуть еще и Boost жирно будет как-то - все равно что забивать почтовые гвозди кувалдой, я попробую лучше стандартными методами QT и ОС реализовать.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 04, 2015, 22:35
Ну да, а сверху еще помазать Boost Asio, но мне тянуть еще и Boost жирно будет как-то - все равно что забивать почтовые гвозди кувалдой, я попробую лучше стандартными методами QT и ОС реализовать.
Ну так в boost.process и можно посмотреть как он это делает в венде.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 04, 2015, 22:38
Ну да, а сверху еще помазать Boost Asio, но мне тянуть еще и Boost жирно будет как-то - все равно что забивать почтовые гвозди кувалдой, я попробую лучше стандартными методами QT и ОС реализовать.
Ну так в boost.process и можно посмотреть как он это делает в венде.

Как раз сейчас смотрю  ;D.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Bepec от Август 04, 2015, 22:52
А можно просто использовать сокеты :D


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 05, 2015, 07:10
А можно просто использовать сокеты :D
Для обеспечения асинхронной работы с сокетами понадобятся такие-же телодвижения.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Пантер от Август 05, 2015, 08:08
Для асинхронного чтения stdin нужно использовать QSocketNotifier. Выдернул из рабочего проекта:
Код
C++ (Qt)
CommandServer::CommandServer(const CComPtr<IBackupRestoreClient>& backupRestoreClient)
       : m_backupRestoreClient(backupRestoreClient)
         , m_stdinNotifier(new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this))
         , m_stdout(new QTextStream(stdout))
         , m_commandHandlersFactory(new CommandHandlersFactory(m_backupRestoreClient))
{
       connect(m_stdinNotifier.data(), &QSocketNotifier::activated, this, &CommandServer::readInputCommands);
}
 



Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 05, 2015, 08:12
Для асинхронного чтения stdin нужно использовать QSocketNotifier. Выдернул из рабочего проекта:
У ТС консольная программа без Qt.
QSocketNotifier умеет отслеживать дескрипторы под вендой?


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Пантер от Август 05, 2015, 08:24
Для асинхронного чтения stdin нужно использовать QSocketNotifier. Выдернул из рабочего проекта:
У ТС консольная программа без Qt.
QSocketNotifier умеет отслеживать дескрипторы под вендой?
Не проверял, но, насколько я знаю, да.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Old от Август 05, 2015, 08:32
Не проверял, но, насколько я знаю, да.
А вот я сомневаюсь. :)
В linux через QSocketNotifier можно пулить любые дескрипторы, там все файл.
А вот в венде даже для последовательного порта, так сказать, свой API. :)


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Пантер от Август 05, 2015, 08:35
Не буду спорить, ибо виндов нету под рукой. В любом случае, можно написать свой вариант для обеих ОС. Не думаю, что это займет много времени. Но сокеты тоже хороший вариант, ибо в любой момент можно программы разнести на разные копмы и все будет работать.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: kuzulis от Август 05, 2015, 08:46
Цитата: Пантер
Не проверял, но, насколько я знаю, да.

Нет. QSocketNotifier можно использовать только для posix-дескрипторов.
В винде это сработает только для сокетов (для которых использовались POSIX совместимые вызовы).

В иных случаях для винды нужно использовать QWinEventNotifier и/или приватный QWinOverlappedIoNotifier,
в зависимости от ситуации.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 05, 2015, 11:58
Не проверял, но, насколько я знаю, да.
Нет, не умеет - я уже это все давно проверил.
QProcess в винде подменяет stdin,stdout,stderr на свои пайпы для приложения через стартовый данные процесса(STARTUPINFO), я хотел дернуть их оттуда, но как оказалось они анонимные и как следствия не асинхронные. А boost судя по всему передает туда named pipes со всеми вытекающими.
Крч. сделать асинхронный stdin в виндовс не тривиальная задача, в 8-ке появляются еще отдельные особенности.
Проще заменить stdin на named pipe в виндовс.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 06, 2015, 13:50
Оказывается что в QT5 они сделали named pipes(\5.4\Src\qtbase\src\corelib\io\qprocess_win.cpp), но как-то криво сделали - нет ни OVERLAPPED ни WaitForMultipleObjects нету.
Непонятно как это еще можно использовать в самой программе клиенте. К примеру я получил и достал оттуда хендл именнованого пайпа stdin:

Цитировать
STARTUPINFO startInfo;
HANDLE hStdInput;
....
GetStartupInfoW(&startInfo);
if( ( STARTF_USESTDHANDLES & startInfo.dwFlags ) == STARTF_USESTDHANDLES &&
     ( hStdInput=startInfo.hStdInput ) != INVALID_HANDLE_VALUE ){
     
   /// как его читать асинхронно здесь?
}

Но как его читать здесь без структуры OVERLAPPED? Ведь если не указать ее для ReadFile будет идти синхронное чтения.
Для Asynchronous I/O нужно ее указывать, но где ее взять?


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Bepec от Август 06, 2015, 13:59
Поэтому переделайте всё на сокеты и будет вам счастье на всех платформах и без подводных камней :D

PS причем переделывать то ничего особо и не надо, дернуть из примера пару функций и всё :)


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: hydra13 от Август 20, 2015, 16:00
QSharedMemory


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: Bepec от Август 20, 2015, 16:09
Есть только 2 способа нормально передавать данные - сокеты и пайпы. Пайпы в винде суровы, им обвязку писать и писать. А сокеты везде одинаковы.


Название: Re: GUI<<->Console обмен сообщениями и данными.
Отправлено: MaxoBik от Август 21, 2015, 22:09
QSharedMemory
Придется плясать с семафорами, да и не нужно это - мои данные почти полностью состоят из текста, которые нужно просто показать пользователя. Крч. я все сделал через пайпы с упаковкой данных в JSON. Именованые пайпы кстати в QT для Windows просто для вида, половина кода не реализована, пришлось писать с нуля.