我正在尝试编写一个应用程序,它将生成一个子进程,并通过标准输出/输入与它进行通信。为了掌握它的诀窍,我尝试编写一个简单的应用程序,它会向子进程发送一条消息,子进程将接收到它并将其发回。坦白地说,经过大量的尝试和错误之后,我成功地向子进程发送了一条消息,但我想不出如何将它发回。
以下是我的尝试:
#include <QApplication>
#include <QDataStream>
#include <QFile>
#include <QDebug>
#include <QProcess>
#include <QThread>
#define dumpval(x) qDebug()<<#x<<'='<<x
void slave()
{
QApplication::setApplicationName("slave");
qSetMessagePattern("%{appname}: %{message}");
qDebug()<<"started";
QFile input;
QFile output;
dumpval(input.open(stdin, QFile::ReadOnly));
dumpval(output.open(stdout, QFile::WriteOnly));
QObject::connect(&output, &QIODevice::bytesWritten, [](int bytesWritten){dumpval(bytesWritten);});
QDataStream inputStream(&input);
QDataStream outputStream(&output);
QByteArray data;
while (true){
inputStream>>data;
dumpval(data);
if (!data.isEmpty()) break;
inputStream.resetStatus();
QThread::sleep(1);
}
dumpval(output.isWritable());
outputStream<<data;
dumpval(output.waitForBytesWritten(-1));
qDebug()<<"data written";
qDebug()<<"stopped";
}
void master(QString path)
{
QApplication::setApplicationName("master");
qSetMessagePattern("%{appname}: %{message}");
qDebug()<<"started";
QProcess p;
QObject::connect(&p, &QIODevice::bytesWritten, [](int bytesWritten){dumpval(bytesWritten);});
p.setProgram(path);
p.setArguments({"slave"});
p.setProcessChannelMode(QProcess::ForwardedErrorChannel);
p.start();
p.waitForStarted();
QDataStream stream(&p);
QByteArray data = "this is a test";
stream<<data;
dumpval(p.waitForBytesWritten(-1));
data.clear();
while (true){
stream>>data;
dumpval(data);
if (!data.isEmpty()) break;
stream.resetStatus();
QThread::sleep(1);
}
qDebug()<<"stopped";
}
int main(int argc, char** argv)
{
if (argc == 1) master(argv[0]);
else slave();
}下面是这个代码的输出:
master: started
master: bytesWritten = 18
master: p.waitForBytesWritten(-1) = true
master: data = ""
slave: started
slave: input.open(stdin, QFile::ReadOnly) = true
slave: output.open(stdout, QFile::WriteOnly) = true
slave: data = "this is a test"
slave: output.isWritable() = true
slave: output.waitForBytesWritten(-1) = false
slave: data written
slave: stopped
master: data = ""
master: data = ""
master: data = ""
master: data = ""
master: data = ""
master: data = ""
^C我做错了什么?
发布于 2017-04-20 20:56:28
QFile不实现异步接口。读写是阻塞的,waitForXxx方法是无操作的.
如果您希望实现非阻塞控制台I/O,请参见this question。
由于QFile是阻塞的,所以slave()不需要一个检查状态的循环。
您使用它的阻塞API使用QProcess,因此没有必要使用它的信号。您还假设读取将返回完整的数据块。控制台I/O是面向流的,而不是面向消息的,因此您必须使用QDataStream事务来确保读取成功。readyRead指示仅仅表明一些数据是可用的。可能只有一个字节。
如果您希望使用无阻塞的有状态方法来处理QProcess和类似的通信,请参见this answer for one approach。
请注意,使用argc[0]作为从服务器启动self是不可靠的。使用QCoreApplication::applicationFilePath()代替。
下面的示例工作正常,并产生以下输出:
master: started
slave: started
slave: input.open(stdin, QFile::ReadOnly) = true
slave: output.open(stdout, QFile::WriteOnly) = true
slave: data = "this is a test\x00"
slave: data = ""
slave: inputStream.status() = 0
slave: stopped
master: data = "this is a test\x00"
master: data = ""
master: stopped// https://github.com/KubaO/stackoverflown/tree/master/questions/process-echo-43523282
#include <QtCore>
#define dumpval(x) qDebug()<<#x<<'='<<x
void slave()
{
QCoreApplication::setApplicationName("slave");
qDebug()<<"started";
QFile input, output;
QDataStream inputStream{&input}, outputStream{&output};
dumpval(input.open(stdin, QFile::ReadOnly));
dumpval(output.open(stdout, QFile::WriteOnly));
QByteArray data;
do {
inputStream >> data;
outputStream << data;
dumpval(data);
} while (inputStream.status() == QDataStream::Ok && !data.isEmpty());
dumpval(inputStream.status());
}
void master()
{
QCoreApplication::setApplicationName("master");
qDebug()<<"started";
QProcess p;
p.setProgram(QCoreApplication::applicationFilePath());
p.setArguments({"slave"});
p.setProcessChannelMode(QProcess::ForwardedErrorChannel);
p.start();
p.waitForStarted();
QDataStream stream(&p);
QByteArray data;
stream << "this is a test" << QByteArray{};
while (true) {
stream.startTransaction();
stream >> data;
if (stream.commitTransaction()) {
dumpval(data);
if (data.isEmpty())
break;
} else
p.waitForReadyRead();
}
p.waitForFinished();
}
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
qSetMessagePattern("%{appname}: %{message}");
if (app.arguments().size() < 2) master(); else slave();
qDebug() << "stopped";
}https://stackoverflow.com/questions/43523282
复制相似问题