-->

How to communicate Qt applications two-way

2019-08-24 02:02发布

问题:

I want to create two-way communicate beetwen my Qt Apps. I want to use QProcess to do this. I'm calling sucesfully child app from root app and sending test data without any erro, but I can't recive any data in child app. I'll be gratefull for any help. I'm using Qt 4.7.1. Below my test code:

Root app:

InterProcess::InterProcess(QObject *parent) : QProcess(parent)
{
    process = new QProcess(this);
    process->start(myChildApp);
    process->waitForStarted();
    process->setCurrentWriteChannel(QProcess::StandardOutput);
    process->write("Test");

    connect( process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(error(QProcess::ProcessError)) );
    connect( process, SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()) );
    connect( process, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()) );     

QByteArray InterProcess::read()
{
    QByteArray readBuffer = process->readAllStandardOutput();
    return readBuffer;
}

void InterProcess::error( QProcess::ProcessError error )
{
    qDebug() << "Error!";
    qDebug() << error;
}

void InterProcess::readyReadStandardError()
{
    qDebug() << "Ready to read error.";
    qDebug() << process->readAllStandardError();
}

void InterProcess::readyReadStandardOutput()
{
    qDebug() << "The output:";
    QByteArray readBuffer = process->readAllStandardOutput();
    qDebug() << readBuffer;
}

Child app:

InterProcess::InterProcess(QObject *parent) : QProcess(parent)
{
    process = new QProcess();
    process->setCurrentReadChannel(QProcess::StandardOutput);

    connect( process, SIGNAL(readyRead()), this, SLOT(readyReadStandardOutput()));
    connect( process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(error(QProcess::ProcessError)) );
    connect( process, SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()) );
    connect( process, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()) );

    process->waitForReadyRead(5000);
}

void InterProcess::readyReadStandardError()
{
    qDebug() << "Ready to read error.";
    qDebug() << process->readAllStandardError();
    setText("REady error");
}

void InterProcess::readyReadStandardOutput()
{
    setMessage("2");
    qDebug() << "The output:";
    QByteArray readBuffer = process->readAllStandardOutput();
    qDebug() << readBuffer;
}
void InterProcess::error( QProcess::ProcessError error )
{
    qDebug() << "Error!";
    qDebug() << error;
    setText(QString(error));
}

回答1:

It's very hard to explain in one answer all mistakes, so just look at code and ask if you still got problems. Here is example of using QProcess as IPC.

This is your main process, that creates additional process and connects to its signals

MyApplicaiton.h

#ifndef MYAPPLICATION_H
#define MYAPPLICATION_H
#include <QApplication>

class InterProcess;
class MyApplication : public QApplication {
    Q_OBJECT
public:
    MyApplication(int &argc, char **argv);
signals:
    void mainApplicationSignal();
private slots:
    void onInterProcessSignal();
private:
    InterProcess *mProcess;
};
#endif // MYAPPLICATION_H

MyApplicaiton.cpp

#include "MyApplication.h"
#include "InterProcess.h"

MyApplication::MyApplication(int &argc, char **argv) : QApplication(argc, argv) {
    mProcess = new InterProcess(this);
    connect(mProcess, SIGNAL(interProcessSignal()),
            this, SLOT(onInterProcessSignal()));
    mProcess->start();
}

void MyApplication::onInterProcessSignal() {}

This is example implementation of your interProcess class:

InterProcess.h

class InterProcess : public QProcess {
    Q_OBJECT
public:
    explicit InterProcess(QObject *parent = nullptr);
signals:
    void interProcessSignal();
private slots:
    void onMainApplicationSignal();
};

InterProcess.cpp

#include "InterProcess.h"
#include "MyApplication.h"


InterProcess::InterProcess(QObject *parent) : QProcess(parent) {
    if(parent) {
        auto myApp = qobject_cast<MyApplication *>(parent);
        if(myApp) {
            connect(myApp, SIGNAL(mainApplicationSignal()),
                    this, SLOT(onMainApplicationSignal()));
        }
    }
}

void InterProcess::onMainApplicationSignal() {}


回答2:

Locally, using UDP is very convenient and efficient

void Server::initSocket() {
  udpSocket = new QUdpSocket(this);
  udpSocket->bind(QHostAddress::LocalHost, 7755);
  connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));}


void Server::readPendingDatagrams(){
  while (udpSocket->hasPendingDatagrams()) {
      QByteArray datagram;
      datagram.resize(udpSocket->pendingDatagramSize());
      QHostAddress sender;
      quint16 senderPort;

      udpSocket->readDatagram(datagram.data(), datagram.size(),
                              &sender, &senderPort);

      processTheDatagram(datagram);
  }}