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操作系 ...
随机推荐
- MCS-51单片机实用子程序库
目前已有若干版本的子程序库公开发表,它们各有特色.本程序库中的开平方算法为快速逼近算法,它能达到牛顿迭代法同样的精度,而速度加快二十倍左右,超过双字节定点除法的速度. 本子程序库对<单片机应用程 ...
- [置顶] css3 befor after 简单使用 制作时尚焦点图相框
:befor.:after是CSS的伪元素,什么是伪元素呢?伪元素用于向某些选择器设置特殊效果. 我们用CSS手册可以查询到其基本的用法: E:before/E::before 设置在对象前(依据对象 ...
- JVM基础和调优(一)
最近的项目中,出现了内存和性能的问题,需要优化,所以趁着这个机会,把自己关于java虚拟机的东整理一下,不对的地方,欢迎指出. 数据类型,因为在java的优化的过程中,检测到的数据类型一般比较的基础, ...
- 关于bootstrap--网格系统
1. 2.偏移列(col-md-offset-*):为了在大屏幕显示器上使用偏移,请使用 .col-md-offset-* 类.这些类会把一个列的左外边距(margin)增加 * 列,其中 * 范围是 ...
- Entify Framewrok - Join的使用方法
问题:有2个表,使用id相连,如何用Join语法将其连接起来? 如下代码 List<tblAssociation> assoList = dataContext.tblAssociatio ...
- loadrunner java 缺少必要的导入包报错
loadrunner 运行从eclipse中做好的脚本,ctrl + A 复制到loadrunner中来, 添加参数化的的语句:verifyCode = lr.eval_string (&quo ...
- uiautomatorviewer 识别android微信元素报错
org.xml.sax.SAXParseException; systemId: file:/C:/Users/xxxxxxxxx/AppData/Local/Temp/uiautomatorview ...
- ajax提交写法
<script> /* ajax提交写法 */ function add_prize() { // var query={}; var query = new Object(); quer ...
- [转] ubuntu 一些常用软件的安装
首先说明一下 ubuntu 的软件安装大概有几种方式: 1. deb 包的安装方式deb 是 debian 系 Linux 的包管理方式, ubuntu 是属于 debian 系的 Linux 发行版 ...
- Android Studio新手全然指引
Android Studio新手全然指引 @author ASCE1885的 Github 简书 微博 CSDN Android Studio的下载及安装 假设你的电脑能够FQ,那么请直接到Andro ...