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
#include
#include
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
#include
#include
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
#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));
}