开源 C++ QT Widget 开发(十)IPC进程间通信--共享内存

文章的目的为了记录使用C++ 进行QT Widget 开发学习的经历。临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 C++ QT Widget 开发(一)工程文件结构-CSDN博客

开源 C++ QT Widget 开发(二)基本控件应用-CSDN博客

开源 C++ QT Widget 开发(三)图表--波形显示器-CSDN博客

开源 C++ QT Widget 开发(四)文件--二进制文件查看编辑-CSDN博客

开源 C++ QT Widget 开发(五)通讯--串口调试-CSDN博客

开源 C++ QT Widget 开发(六)通讯--TCP调试-CSDN博客

开源 C++ QT Widget 开发(七)线程--多线程及通讯-CSDN博客

开源 C++ QT Widget 开发(八)网络--Http文件下载-CSDN博客

开源 C++ QT Widget 开发(九)图表--仪表盘-CSDN博客

推荐链接:

开源 java android app 开发(一)开发环境的搭建-CSDN博客

开源 java android app 开发(二)工程文件结构-CSDN博客

开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客

开源 java android app 开发(四)GUI界面重要组件-CSDN博客

开源 java android app 开发(五)文件和数据库存储-CSDN博客

开源 java android app 开发(六)多媒体使用-CSDN博客

开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客

开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客

开源 java android app 开发(九)后台之线程和服务-CSDN博客

开源 java android app 开发(十)广播机制-CSDN博客

开源 java android app 开发(十一)调试、发布-CSDN博客

开源 java android app 开发(十二)封库.aar-CSDN博客

推荐链接:

开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

本章主要内容:Qt 的共享内存 (QSharedMemory) 实现的进程间通信 (IPC) 应用程序。

目录:

1.主要功能

2.源码分析

3.所有源码

4.效果演示

一、主要功能

这个应用程序实现了两个进程间通过共享内存进行通信的功能:

发送消息:将文本消息写入共享内存

接收消息:从共享内存读取消息并显示

自动检测:定时检查共享内存中是否有新消息

二、源码分析

  1. Mainwindow.h文件

使用 QSharedMemory 实现共享内存功能

使用 QTimer 定期检查共享内存

定义了三个主要槽函数对应按钮点击事件

包含共享内存设置和状态更新方法

  1. Mainwindow.cpp文件

setupSharedMemory():

尝试创建共享内存(如果不存在)

如果已存在则附加到现有共享内存

处理创建/附加失败的情况

on_sendButton_clicked():

检查并附加到共享内存

将消息和时间戳序列化到缓冲区

锁定共享内存并复制数据

更新状态并清空输入框

on_receiveButton_clicked():

从共享内存读取数据

反序列化消息和时间戳

格式化并显示接收到的消息

checkSharedMemory():

定时检查共享内存中是否有新消息

有消息时更新状态标签的样式提示用户

updateStatus():

更新状态标签并设置临时样式

3秒后恢复默认状态

三、所有源码

  1. mianwindow.h文件

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QSharedMemory>
    #include <QTimer>

    QT_BEGIN_NAMESPACE
    namespace Ui {
    class MainWindow;
    }
    QT_END_NAMESPACE

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    private slots:
    void on_sendButton_clicked();
    void on_receiveButton_clicked();
    void on_clearButton_clicked();
    void checkSharedMemory();

    private:
    Ui::MainWindow *ui;
    QSharedMemory *sharedMemory;
    QTimer *checkTimer;

    复制代码
     void setupSharedMemory();
     void updateStatus(const QString &message);

    };
    #endif // MAINWINDOW_H

  2. mainwindow.cpp文件

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QBuffer>
    #include <QDataStream>
    #include <QMessageBox>
    #include <QDateTime>
    #include <QDebug>

    MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , sharedMemory(new QSharedMemory("MyAppSharedMemory", this))
    {
    ui->setupUi(this);

    复制代码
     // 设置界面初始状态
     ui->statusLabel->setText("就绪");
     ui->statusLabel->setStyleSheet("QLabel { background-color: lightgray; padding: 5px; }");
    
     // 设置共享内存
     setupSharedMemory();
    
     // 创建定时器定期检查共享内存
     checkTimer = new QTimer(this);
     connect(checkTimer, &QTimer::timeout, this, &MainWindow::checkSharedMemory);
     checkTimer->start(1000); // 每秒检查一次
    
     // 设置初始消息
     ui->messageEdit->setText("你好,这是来自QT共享内存的消息!");

    }

    MainWindow::~MainWindow()
    {
    // 清理共享内存
    if (sharedMemory->isAttached()) {
    sharedMemory->detach();
    }
    delete ui;
    }

    void MainWindow::setupSharedMemory()
    {
    // 尝试创建或附加到共享内存
    if (!sharedMemory->create(1024) && sharedMemory->error() == QSharedMemory::AlreadyExists) {
    if (sharedMemory->attach()) {
    updateStatus("已连接到现有共享内存");
    } else {
    updateStatus("无法附加到共享内存: " + sharedMemory->errorString());
    }
    } else if (sharedMemory->isAttached()) {
    updateStatus("已创建新的共享内存");
    } else {
    updateStatus("无法创建共享内存: " + sharedMemory->errorString());
    }
    }

    void MainWindow::on_sendButton_clicked()
    {
    if (!sharedMemory->isAttached() && !sharedMemory->attach()) {
    updateStatus("无法附加到共享内存: " + sharedMemory->errorString());
    return;
    }

    复制代码
     QString message = ui->messageEdit->text();
     if (message.isEmpty()) {
         QMessageBox::warning(this, "警告", "消息不能为空!");
         return;
     }
    
     // 准备数据
     QBuffer buffer;
     buffer.open(QBuffer::ReadWrite);
     QDataStream out(&buffer);
    
     // 写入消息和时间戳
     out << message;
     out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    
     // 写入共享内存
     sharedMemory->lock();
     char *to = static_cast<char*>(sharedMemory->data());
     const char *from = buffer.data().data();
     memcpy(to, from, qMin(sharedMemory->size(), static_cast<int>(buffer.size())));
     sharedMemory->unlock();
    
     updateStatus("消息已发送到共享内存: " + message);
     ui->messageEdit->clear();

    }

    void MainWindow::on_receiveButton_clicked()
    {
    if (!sharedMemory->isAttached() && !sharedMemory->attach()) {
    updateStatus("无法附加到共享内存: " + sharedMemory->errorString());
    return;
    }

    复制代码
     // 从共享内存读取数据
     sharedMemory->lock();
     QByteArray byteArray(static_cast<const char*>(sharedMemory->constData()), sharedMemory->size());
     sharedMemory->unlock();
    
     QBuffer buffer(&byteArray);
     buffer.open(QBuffer::ReadOnly);
     QDataStream in(&buffer);
    
     QString message;
     QString timestamp;
     in >> message >> timestamp;
    
     if (message.isEmpty()) {
         ui->receivedTextEdit->append("没有可用的消息");
     } else {
         QString displayText = QString("[%1] %2").arg(timestamp, message);
         ui->receivedTextEdit->append(displayText);
         updateStatus("收到新消息: " + message);
     }

    }

    void MainWindow::on_clearButton_clicked()
    {
    ui->receivedTextEdit->clear();
    updateStatus("已清除接收的消息");
    }

    void MainWindow::checkSharedMemory()
    {
    // 定期检查共享内存中是否有新数据
    if (!sharedMemory->isAttached() && !sharedMemory->attach()) {
    return;
    }

    复制代码
     sharedMemory->lock();
     QByteArray byteArray(static_cast<const char*>(sharedMemory->constData()), sharedMemory->size());
     sharedMemory->unlock();
    
     QBuffer buffer(&byteArray);
     buffer.open(QBuffer::ReadOnly);
     QDataStream in(&buffer);
    
     QString message;
     QString timestamp;
     in >> message >> timestamp;
    
     if (!message.isEmpty()) {
         // 更新状态提示有新消息
         ui->statusLabel->setText("有新消息可用!");
         ui->statusLabel->setStyleSheet("QLabel { background-color: lightgreen; padding: 5px; }");
     }

    }

    void MainWindow::updateStatus(const QString &message)
    {
    ui->statusLabel->setText(message);
    ui->statusLabel->setStyleSheet("QLabel { background-color: lightblue; padding: 5px; }");

    复制代码
     // 3秒后恢复普通状态
     QTimer::singleShot(3000, this, [this]() {
         ui->statusLabel->setText("就绪");
         ui->statusLabel->setStyleSheet("QLabel { background-color: lightgray; padding: 5px; }");
     });

    }

  3. mainwindow.ui文件

在工程文件夹下用记事本打开

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>600</width>
    <height>400</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>QT共享内存IPC示例</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QLabel" name="label">
      <property name="text">
       <string>发送消息:</string>
      </property>
     </widget>
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <item>
       <widget class="QLineEdit" name="messageEdit"/>
      </item>
      <item>
       <widget class="QPushButton" name="sendButton">
        <property name="text">
         <string>发送</string>
        </property>
       </widget>
      </item>
     </layout>
    </item>
    <item>
     <widget class="QLabel" name="label_2">
      <property name="text">
       <string>接收的消息:</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QTextEdit" name="receivedTextEdit"/>
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout_2">
      <item>
       <widget class="QPushButton" name="receiveButton">
        <property name="text">
         <string>接收消息</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="clearButton">
        <property name="text">
         <string>清除</string>
        </property>
       </widget>
      </item>
      <item>
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </item>
    <item>
     <widget class="QLabel" name="statusLabel"/>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

四、效果演示

输入消息

发送消息

接收消息

相关推荐
FIT2CLOUD飞致云7 小时前
学习笔记 | 如何将MaxKB应用对外发布为MCP服务?
人工智能·开源
忆萧7 小时前
C++智能指针
c++
劲镝丶7 小时前
51单片机的电子音乐盒 (详细教程)
c语言·c++·单片机·嵌入式硬件·51单片机
努力努力再努力@李7 小时前
利用本地电脑上的MobaXterm连接虚拟机上的Ubuntu
linux·运维·ubuntu
long_run8 小时前
C++之成员初始化列表
c++
Natsume17108 小时前
音视频开发入门:FFmpeg vs GStreamer,新手该如何选择?
c语言·c++·ffmpeg·音视频·webrtc·实时音视频·视频编解码
是店小二呀8 小时前
Linux | 走进网络世界:MAC、IP 与通信的那些事
linux·网络·macos
linux开发之路8 小时前
C++精选面试题集合(100份大厂面经提取的200+道真题)
linux·c++·网络编程·数据结构与算法·c++面试题
long_run8 小时前
C++之头文件 (.h)
c++