一口气搞懂Qt的所有IPC方式本文转载请联系老吴的嵌入式漫游公众号。大家好,我是老吴。今天整理一下Qt中几个重要的IPC方法。InternetSocketQt中的QtNetwork模块提供了一些类使网络编程更简单,并且支持跨平台。具体来说,有上层的QNetworkAccessManager、QNetworkRequest、QNetworkReply。以及底层的QTcpSocket、QTcpServer、QUdpSocket。示例https://doc.qt.io/qt-5/qtnetwork-downloadmanager-example.html这个例子演示了如何使用QNetworkAccessManager实现一个命令行下载工具,类似于wget命令。运行效果:$./downloadmanagerhttps://dl.google.com/linux/direct/google-chrome-stable_current_amd64.debDownloadinghttps://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb...[##################################################]100%21.1MB/sSucceeded.1/1filesdownloadedsucceededsuccessfully支持进度显示和多文件排队下载。代码分析//sendrequestvoidDownloadManager::startNextDownload(){QNetworkRequestrequest(url);//managerisQNetworkAccessManager,//currentDownloadisQNetworkReplycurrentDownload=manager.get(request);connect(currentDownload,SIGNAL(readyRead()),SLOT(downloadReadyRead()));}//downloaddatavoidDownloadManager::downloadReadyRead(){//outputisQFileoutput.write(currentDownload->readAll());}3步:发送Request,获取Reply,从Reply中读写数据。更详细的描述:https://doc.qt.io/qt-5/qtnetwork-index.htmlLocalSocketLocalSocket用于同一台计算机上运行的进程之间的通信,相关的类有QLocalServer和QLocalSocket。虽然Internet套接字可用于相同目的,但本地套接字效率更高。LocalSockets只复制数据,不进行协议处理,不需要添加或删除网络头,不需要计算校验和,不生成序列号,不需要发送确认消息。此外,如果以后有需要,它可以很容易地升级到跨主机版本。示例1.财富服务器https://doc.qt.io/qt-5/qtcore-ipc-localfortuneserver-example.html这个例子演示了如何使用QLocalServer实现一个随机答案服务器。2.fortuneclienthttps://doc.qt.io/qt-5/qtcore-ipc-localfortuneclient-example.html本例演示如何使用QLocalSocket连接LocalSocketServer。运行效果:在客户端点击“GetForturn”按钮,会发起一个连接,当服务端发现新的连接时,会随机发送一句话。代码分析服务器端://createalocalsocketserverServer::Server(QWidget*parent):QDialog(parent){server=newQLocalServer(this);server->listen("fortune")connect(server,&QLocalServer::newConnection,this,&Server::sendFortune);}//senddatavoidServer::sendFortune(){QLocalSocket*clientConnection=server->nextPendingConnection();clientConnection->write(block);clientConnection->flush();clientConnection->disconnectFromServer();}4第一步是:新建一个套接字;使用listen()进行监听;使用nextPendingConnection()获取连接;常规的读()/写()操作;客户端的代码也很简单,请自行查看。SharedMemoryQSharedMemory用于支持跨平台共享内存,允许多个线程和进程安全地访问共享内存段。此外,QSystemSemaphore可用于控制对系统共享资源的访问和进程之间的通信。例子https://doc.qt.io/qt-5/qsharedmemory.html这个例子演示了如何使用QSharedMemory在进程间共享内存进行通信。该程序需要启动两次,其中一次先加载一张图片,然后另一个程序通过共享内存访问同一张图片。运行效果:代码分析创建共享内存:voidDialog::loadFromFile(){[...]//loadbufferintosharememory//bufferisQBuffersharedMemory.create(size))sharedMemory.lock();char*to=(char*)sharedMemory。data();constchar*from=buffer.data().data();memcpy(to,from,qMin(sharedMemory.size(),size));sharedMemory.unlock();}访问共享内存:voidDialog::loadFromMemory(){sharedMemory.attach();sharedMemory.lock();buffer.setData((char*)sharedMemory.constData(),sharedMemory.size());buffer.open(QBuffer::ReadOnly);in>>image;sharedMemory.unlock();sharedMemory.detach();ui.label->setPixmap(QPixmap::fromImage(image));}接口很简单:create()创建一块共享内存;attach()和detach()用于访问;lock()和unlock()用于同步;D-Bus协议D-Bus是一种最初为Linux开发的进程间通信(IPC)和远程过程调用(RPC)机制,使用统一的协议替代现有的IPC方案。D-Bus实际上是基于UnixSocket的。它只是提供了一个标准化的总线架构,允许许多进程相互通信。Qt提供了QtDBus模块,将信号槽机制扩展到进程级别,使得开发者可以在一个进程中发送信号,其他进程的槽函数响应信号。例子https://doc.qt.io/qt-5/qtdbus-chat-example.html这个例子演示了如何使用QtDBus实现一个基于D-Bus的简单聊天室。运行效果:代码分析ChatMainWindow::ChatMainWindow():m_nickname(QLatin1String("nickname")){[...]connect(sendButton,SIGNAL(clicked(bool)),this,SLOT(sendClickedSlot()));//addourD-BusinterfaceandconnecttoD-BusnewChatAdaptor(this);QDBusConnection::sessionBus().registerObject("/",this);org::example::chat*iface;iface=neworg::example::chat(QString(),QString(),QDBusConnection::sessionBus(),这个);QDBusConnection::sessionBus().connect(QString(),QString(),"org.example.chat","message",this,SLOT(messageSlot(QString,QString)));[...]}接口感觉比较复杂,这里就不分析了。更详细的说明:https://doc.qt.io/qt-5/qtdbus-index.htmlhttps://unix.stackexchange.com/questions/604258/what-is-d-bus-practical-useful-forQProcessQProcess类可用于将外部程序作为子进程启动并与它们通信。示例代码QProcessgzip;gzip.start("gzip",QStringList()<<"-c");if(!gzip.waitForStarted())returnfalse;gzip.write("Qtrocks!");gzip.closeWriteChannel();如果(!gzip.waitForFinished())返回假;QByteArrayresult=gzip.readAll();这里通过QProcess调用gzip命令解压文件,通信接口为read()/write()。Qt官方没有提供例子。如果你想看例子,可以参考我之前的文章:小子,你想为你的Linux系统写一个启动器吗?这里介绍一下Qt中几个重要的IPC机制。感谢您阅读。
