QProcess進程間雙向通信


記得以前寫過Linux的C程序, 里面用popen打開一個子進程, 這樣可以用read/write和子進程通訊, 而在子進程里則是通過從stdin讀和向stdout寫實現對父進程的通訊。 QProcess的底層實現用的是類似的理念。 QProcess類提供的API讓父進程可以輕松地讀取子進程stdout的數據, 也可以輕松地向子進程的stdin寫數據。 不過這其中還是會有各種各樣頗讓人費解的謎團, 需要memo一下。

Test Case

兩個小程序, 父進程程序名為server。 其中定義了一個QProcess, 將QProcess的readyRead信號連接到一個槽函數上, 用來接收client端stdout上的信息。 在按下“Send to Client”按鈕時調用QProcess::write發送編輯框里的文字。

子進程名為client, 定義一個QFile打開stdin, 連接readyRead信號等待server端寫入的數據。 按下“Send message”時向stdout寫入數據。

大家覺得這個test case能如我們預料那樣正常運行嗎?

問題分析

這個程序從結構上來看非常簡單, 如果代碼不亂寫不像是會出問題的樣子。 實際運行的結果還是頗讓人意外的, 從client端向server端發送數據很正常, 但在client里始終收不到readyRead信號!  雙向交流變成了單向, 這可真讓人郁悶。 仔細看QFile的文檔包括QIODevice有關的描述, 看不出問題所在。 不得已只好求助專家拉, 按照專家的意見, QFile是不支持readyRead信號的。 這一點比較好理解。 但是似乎沒有什么好的Qt API可以解決此問題。

Qt的API設計里沒有包括最底層設備處理的類, 這個問題經常看到有人埋怨, 比如串口通訊等功能就沒有直接的Qt類可用。 不過嘛筆者覺得這個不算什么問題, 像這種特別底層的東西API超簡單, open->ioctl->read/write->close就完事,就算拿Qt包一層也不會更簡單 , 何必多此一舉呢, 如果什么功能都依賴Qt實現, 那要我們這些程序員干啥用?!

這里就需要把原來用QFile來操作stdin的代碼修改成直接open/read/write/close的方式。 如果要保持原來的“有事件才動作”也不是難事, 這部分可以用Qt里的QSocketNotifier類監控fd的讀寫事件, 在收到信號時才去調用read/write。

 

主要代碼

server端開進程
if(! pro )
{
pro = new QProcess(this);
connect(pro, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
connect(pro, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
connect(pro, SIGNAL(readyRead()), this, SLOT(readFromClient()));
pro->start(“./client”);
}

server端接收數據
void MainWin::readFromClient()
{
if( !pro) return;
QByteArray output = pro->readAllStandardOutput();
qWarning() }

server端發送數據
void MainWin::writeToClient()
{
if( !pro) return;
pro->write(le->text().toLatin1().constData(), le->text().length());
qWarning() text();
}

client端監控stdin的讀寫消息
filein.open(stdin, QIODevice::ReadOnly);
QSocketNotifier* sn = new QSocketNotifier(filein.handle(), QSocketNotifier::Read, this);
connect(sn, SIGNAL(activated(int)), this, SLOT(readFromServer(int)));

client端接收數據
void MainWin::readFromServer(int fd)
{
if(fd != filein.handle() )
return;

char buffer[256];
int count = read(filein.handle(), buffer, 256);
le->setText(“FROM SERVER:” + QString(buffer).left(count));
}

client端發送數據
void MainWin::writeToServer()
{
QFile fileout;
fileout.open(stdout, QIODevice::WriteOnly);
fileout.write(le->text().toLatin1().constData(), le->text().length()); // write to stderr
qWarning() text();
fileout.close();
}

轉載至:http://blog.chinaunix.net/uid-13830775-id-97752.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM