QProcess实现进程通信

本文详细介绍了使用Qt库中的QProcess组件实现进程间通信的方法。通过QProcess,父进程可以向子进程发送数据并监听子进程的输出。子进程则通过QFile和QSocketNotifier读取和发送数据。特别地,文章指出子进程不能直接使用QFile的readLine方法读取父进程信息,而应借助unstd.h的read接口。同时,展示了父进程和子进程的代码示例,演示了如何开启进程、发送和接收数据以及处理进程结束的信号。

QProcess实现进程通信的方式有点类似于管道。

QProcess父进程通过write来写入标准输入stdin,通过ReadyRead信号来接收子进程的消息。

QProcess子进程通过QFile来读取标准输入来接收父进程信息。通过QFile绑定QSocketNotifier来接收标准输入的实时信号,因为QSocketNotifier的activated信号可以通过标准输入是否有消息实时触发。

QProcess子进程通过QFile绑定标准输出stdout来发送消息给父进程。

注意:子进程读取信息不能通过QFile的readline等接口读取父进程信息,因为QFile他会读取标准输入的所有信息,并且不到长度就没有返回。哪怕QFile设置了读取长度,也会在满足长度后才有消息返回,我也不知为啥会这样。所有需要通过unstd.h的read接口来读取标准输入。

父进程:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QProcess>
#include <QtWidgets>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void slotopenprocess();
    void slotsenddata();
    void slotfinish(int code);
    void slotreaddata();
private:
    Ui::MainWindow *ui;
    QPushButton* m_btn;
    QPushButton* m_sendbtn;
    QLineEdit* m_edit;
    QTextEdit* m_readedit;
    QProcess* m_process;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("server");
    m_btn = new QPushButton("打开进程",this->centralWidget());
    m_sendbtn = new QPushButton("发送",this->centralWidget());
    m_edit = new QLineEdit(this);
    m_readedit = new QTextEdit(this);
    m_process = new QProcess(this);

    QVBoxLayout* lay = new QVBoxLayout(this);
    lay->addWidget(m_btn);
    lay->addWidget(m_edit);
    lay->addWidget(m_sendbtn);
    lay->addWidget(m_readedit);
    lay->addWidget(m_sendbtn);
    this->centralWidget()->setLayout(lay);

    connect(m_btn,SIGNAL(clicked()),this,SLOT(slotopenprocess()));
    connect(m_sendbtn,SIGNAL(clicked()),this,SLOT(slotsenddata()));
    connect(m_process,SIGNAL(finished(int)),this,SLOT(slotfinish(int)));
    connect(m_process,SIGNAL(readyRead()),this,SLOT(slotreaddata()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slotopenprocess()
{
    m_process->start("/home/yjd/yjd/test/myprocess/myprocess");
}

void MainWindow::slotsenddata()
{
    if (m_process->isOpen())
        m_process->write(m_edit->text().toUtf8());
}

void MainWindow::slotfinish(int code)
{
    qWarning()<<"process finish"<<code<<m_process->readAllStandardOutput();
}

void MainWindow::slotreaddata()
{
    m_readedit->append(QString("接收消息:%1").arg(m_process->readAllStandardOutput().data()));
}

子进程:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QProcess>
#include <QtWidgets>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void slotopenprocess();
    void slotsenddata();
    void slotfinish(int code);
    void slotreaddata(int fd);
private:
    Ui::MainWindow *ui;
    QPushButton* m_btn;
    QPushButton* m_sendbtn;
    QLineEdit* m_edit;
    QTextEdit* m_readedit;
    QProcess* m_process;
    QSocketNotifier* m_clientsocket;
    QFile m_file;
};

#endif // MAINWINDOW_H

#include "mainwindow.h"
#include <unistd.h>
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("client");
    m_btn = new QPushButton("打开进程",this->centralWidget());
    m_sendbtn = new QPushButton("发送",this->centralWidget());
    m_edit = new QLineEdit(this);
    m_readedit = new QTextEdit(this);
    m_process = new QProcess(this);

    QVBoxLayout* lay = new QVBoxLayout(this);
    lay->addWidget(m_btn);
    lay->addWidget(m_edit);
    lay->addWidget(m_sendbtn);
    lay->addWidget(m_readedit);
    lay->addWidget(m_sendbtn);
    this->centralWidget()->setLayout(lay);

    connect(m_btn,SIGNAL(clicked()),this,SLOT(slotopenprocess()));
    connect(m_sendbtn,SIGNAL(clicked()),this,SLOT(slotsenddata()));
    connect(m_process,SIGNAL(finished(int)),this,SLOT(slotfinish(int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slotopenprocess()
{
    m_file.open(stdin, QFile::ReadOnly);
    if (m_file.isOpen())
    {
        m_clientsocket = new QSocketNotifier(m_file.handle(), QSocketNotifier::Read,this);
        connect(m_clientsocket,SIGNAL(activated(int)),this,SLOT(slotreaddata(int)));
        QMessageBox::information(this,"title","open success");
    }
}

void MainWindow::slotsenddata()
{
    QFile file;
    file.open(stdout, QFile::WriteOnly);
    file.write(m_edit->text().toUtf8());
}

void MainWindow::slotfinish(int code)
{
    qWarning()<<"process finish"<<code<<m_process->readAllStandardOutput();
}

void MainWindow::slotreaddata(int fd)
{
    if(fd != m_file.handle() )
    return;

    char buf[128] = {0};
    read(fd,buf,sizeof(buf));     //不建议使用m_file.readLine(5)来读取返回值
    m_readedit->append(QString::fromUtf8("接收消息:%1").arg(buf));

}

在这里插入图片描述

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值