QProcess и QLocalSocket - сообщения IPC не принимаются - PullRequest
2 голосов
/ 01 апреля 2019

По примеру Fortune Client .

Имеет подкласс QLocalServer, который запускает другое приложение (клиент), используя Qprocess, и этот клиент будет отправлять некоторые сообщения, используя QLocalSocket. В основном (серверном) приложении появляется только первое сообщение от клиента, которое также только при выходе из клиентского процесса.

серверное приложение:

localserver.h

#ifndef LOCALSERVER_H
#define LOCALSERVER_H

#include <QLocalServer>

class LocalServer : public QLocalServer
{
    Q_OBJECT

public:

    explicit LocalServer(QObject* prnt = nullptr);
};

#endif // LOCALSERVER_H

localserver.cpp

#include "localserver.h"

#include <QLocalSocket>
#include <QDebug>

LocalServer::LocalServer(QObject* prnt)
    : QLocalServer(prnt)
{
    connect(this, &QLocalServer::newConnection, this, [&]() {
        qDebug() << "Socket connected";
        QLocalSocket* socket = this->nextPendingConnection();
        connect(socket, &QLocalSocket::disconnected, socket, &QLocalSocket::deleteLater);
        connect(socket, &QLocalSocket::readyRead, [&, socket]() {
            qDebug() << socket->readAll();
        });
    });
}

main.cpp (сервер)

#include <QCoreApplication>
#include <QProcess>

int main(int argc, char* argv[])
{
    QCoreApplication a(argc, argv);

    LocalServer::removeServer("testServer");
    LocalServer server;

    if (server.listen("testServer")) {
        QProcess process;
        process.setProgram("/home/ram/work/build/QtExamples/build-LocalSocketClient-Qt_5_12_1_Desktop-Debug/LocalSocketClient");
        process.start();

        if (process.waitForStarted() && process.waitForFinished()) {
            a.exit(0);
        }
    }

    return a.exec();
}

клиентское приложение:

main.cpp (клиент)

#include <QCoreApplication>

#include <QLocalSocket>
#include <QTimer>
#include <QDebug>

int main(int argc, char* argv[])
{
    QCoreApplication a(argc, argv);

    QLocalSocket localSocket;

    QObject::connect(&localSocket, &QLocalSocket::connected, &localSocket, []() {
        qDebug() << "Socket connected";
    });

    localSocket.setServerName("testServer");
    localSocket.connectToServer();

    if (localSocket.waitForConnected()) {
        qDebug() << "Connected!";
        auto timer = new QTimer(qApp);
        QObject::connect(timer, &QTimer::timeout, &localSocket, [&localSocket]() {
            static int msgCount(0);
            QString msg(QString("Message from client %1").arg(++msgCount));
            qDebug() << localSocket.write(msg.toLatin1()) << msg;

            if (msgCount > 5) {
                qApp->exit(0);
            }
        });
        timer->start(1000);
    } else {
        return 1;
    }

    return a.exec();
}

Когда я запускаю два приложения по отдельности, т.е. без Qprocess части в main.cpp в серверном приложении, я вижу следующий вывод.

Socket connected
"Message from client 1"
"Message from client 2"
"Message from client 3"
"Message from client 4"
"Message from client 5"

При QProcess все пять сообщений появляются одновременно.

Socket connected
"Message from client 1Message from client 2Message from client 3Message from client 4Message from client 5"

Я что-то здесь упускаю? QProcess нужна дополнительная информация?

Также я попытался использовать функцию system() - она ​​вела себя так же.

1 Ответ

1 голос
/ 01 апреля 2019

Никогда не используйте методы waitXXX, потому что они блокируют цикл обработки событий, в котором передаются сигналы. В вашем случае данные получаются один за другим, но поскольку никто не потребляет информацию, так как сигнал не передается, он накапливается в буфере и показывает только, когда цикл событий не заблокирован, показывая весь текст. Таким образом, решение в вашем случае заключается не в использовании waitXXX, а в использовании сигналов:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    LocalServer::removeServer("testServer");
    LocalServer server;

    if (server.listen("testServer")) {
        QProcess process;
        process.setProgram("/home/ram/work/build/QtExamples/build-LocalSocketClient-Qt_5_12_1_Desktop-Debug/LocalSocketClient");
        process.start();
        QObject::connect(&process, QOverload<int>::of(&QProcess::finished), &QCoreApplication::quit);
        return a.exec();
    }
    return 0;
}
...