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
QProcess进程间双向通信的更多相关文章
- 输入系统:进程间双向通信(socketpair+binder)
一.双向通信(socketpair) socketpair()函数用于创建一对无名的.相互连接的套接子,如果函数成功,则返回0,创建好的套接字分别是sv[0]和sv[1]:否则返回-1,错误码保存于e ...
- Qt学习之路(58): 进程间交互(QProcess.readAllStandardOutput可以读取控制台的输出)
所谓 IO 其实不过是与其他设备之间的数据交互.在 Linux 上这个概念或许会更加清楚一些.Linux 把所有设备都看作是一种文件,因此所有的 IO 都归结到对文件的数据交互.同样,与其他进程之间也 ...
- Android进程间通讯之messenger
这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下. 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都 ...
- Android进阶笔记04:Android进程间通讯(IPC)之Messenger
一. Android进程间通讯之Messenger 的引入 (1)引言: 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...
- Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- python 全栈开发,Day40(进程间通信(队列和管道),进程间的数据共享Manager,进程池Pool)
昨日内容回顾 进程 multiprocess Process —— 进程 在python中创建一个进程的模块 start daemon 守护进程 join 等待子进程执行结束 锁 Lock acqui ...
- python全栈开发day33-进程间的通信、进程间的数据共享,进程池
一.昨日内容回顾: 1. 守护进程 1).p.saemon, 2 ).p.terminate 3 ).p.join 2. 同步控制 1).锁,Lock 互斥锁,解决数据安全.进程之间资源抢占问题. ...
- Linux 进程间通讯
一.Linux 下进程间通讯方式 1)管道(Pipe)及有名管道(named pipe): 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- Windows进程间各种通信方式浅谈
1 Windows进程间通信的各种方法 进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码.数据以及它可利用的系统资源(如文件.管道等)组成. 多进程/多线程是Windows操作系 ...
随机推荐
- Python 坑爹之 代码缩进
建议:统一使用空格!!!!!!!!!不要Tab Python代码缩进 这两天python-cn邮件列表有一条thread发展的特别长,题目是<python的代码缩进真是坑爹>(地址), ...
- MySQL的SQL_CALC_FOUND_ROWS真的很慢么?
分页程序一般由两条SQL组成: SELECT COUNT(*) FROM ... WHERE .... SELECT ... FROM ... WHERE LIMIT ... 如果使用SQL_CALC ...
- bzoj3629[JLOI2014]聪明的燕姿
http://www.lydsy.com/JudgeOnline/problem.php?id=3629 搜索. 我们知道: 如果$N=\prod\limits_{i=1}^{m}p_{i}^{k_{ ...
- 最快速的“高斯”模糊算法(附Android源码)
这是一个外国人的算法,本人是搬运工.参考:http://blog.ivank.net/fastest-gaussian-blur.html 1:高斯模糊算法(参考:http://www.rua ...
- 关于maven-jetty-plugin 自动重启问题
<plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin ...
- java之File
1.文件创建.重命名.删除 code: package com.test; import java.io.File; import java.io.IOException; public class ...
- [原创作品]手把手教你怎么写jQuery插件
这次随笔,向大家介绍如何编写jQuery插件.啰嗦一下,很希望各位IT界的‘攻城狮’们能和大家一起分享,一起成长.点击左边我头像下边的“加入qq群”,一起分享,一起交流,当然,可以一起吹水.哈,不废话 ...
- mysql三种binlog日志的理解
最近,一直在纠结要不要改数据库binlog的日志格式,原先用的是row格式,导致数据库binlog日志较大,磁盘空间本来也不是很大,所以就想看看能不能改变binlog日志.在该binlog日志之前,先 ...
- Linux的启动流程
1.首先是bios加电自检.初始化,这个过程会检测相关硬件(cpu.内存.硬盘等),然后会读取硬盘中的MBR:2.加载内核,读取/boot里边的配置文件:3.启动初始化进程,开始运行/sbin/ini ...
- aspx生成验证码
//定义方法 public partial class VerificationCode : System.Web.UI.Page { string ImagePath = &qu ...