QProcess和QLocalSocket - 无法接收IPC消息

3

跟随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();
        });
    });
}

主要代码文件.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();
}

客户端应用:

主文件.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();
}

当我分别运行两个应用程序时,即在服务器应用程序的main.cpp中没有QProcess部分时,我会看到以下输出。
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() 函数 - 它的表现相同。


这真的需要一个 [mcve],但我怀疑问题的一部分是由于有两个名为“timer”的 QTimer 实例之一会遮盖另一个。你正在使用的那个将在调用 timer.start 后立即超出范围并被销毁。 - G.M.
1
好的,但如果新编辑的代码是正确的,那么变量名遮蔽已经消失了,但作用域问题仍然存在--你启动计时器,然后它立即被销毁。 - G.M.
connect(timer, ... 更改为 connect(&timer, ... - eyllanesc
if (cient.waitForStarted() && 更改为 if (client.waitForStarted() && - eyllanesc
你的代码并没有帮助,因为它有很多不一致之处,你必须提供一个 [mcve]。 - eyllanesc
显示剩余4条评论
1个回答

2
不要使用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;
}

谢谢,这个方法可行。我知道waitForFinished是一个阻塞调用,但没想到它也会阻塞网络套接字相关的活动。好吧,吸取教训。 :-) - ramtheconqueror

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接