消息队列通信

#ifndef MSGQUEUE_H
#define MSGQUEUE_H

#include <QObject>
#include <mqueue.h>
#include <thread>
#include <QSharedPointer>
#include <QMutex>
#include <QVariantMap>

class MsgQueue : public QObject
{
    Q_OBJECT
public:
    explicit MsgQueue(QObject *parent = nullptr);

    ~MsgQueue();

    // 获取通信对象
    static MsgQueue *getInstance();

    // 下发消息到消息进程
    void pushCmdToSlave(QJsonObject jsObj);

    // 获取消息进程响应消息
    QVariantMap getReceiveCmd();

    // 将来自界面的数据存储到发送列表中
    Q_INVOKABLE void appendModuleData(const QVariantMap& vMap);

signals:
    void sig_recvCmd(QVariantMap vMap);
private:
    // 初始化消息队列
    void initMsgQueue();
    // 发送数据
    void sendData();
    // 接收数据
    void recvData();
private:
    mqd_t msg_qt_to_com{-1}; // qt_to_com消息队列描述符
    mqd_t msg_com_to_qt{-1}; // com_to_qt消息队列描述符
    QSharedPointer<std::thread> m_sendThread{nullptr};
    QSharedPointer<std::thread> m_recvThread{nullptr};
    QList<QVariantMap> m_sendList;
    QMutex m_sendMutex;
};

#endif // MSGQUEUE_H
#include "msgqueue.h"
#include <QScopedPointer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QThread>
#include <QDebug>

#define COMM_UIB_QT_TO_COM_NAME "/posix_msg_qt_to_com" // qt to communication
#define COMM_UIB_COM_TO_QT_NAME "/posix_msg_com_to_qt" // communication to qt

static bool flag = true;

MsgQueue::MsgQueue(QObject *parent)
    : QObject{parent}
{
    m_sendList.clear();
    initMsgQueue();
    m_recvThread = QSharedPointer<std::thread>(new std::thread(&MsgQueue::recvData, this));
}

MsgQueue::~MsgQueue()
{
    flag = false;

    if (!m_sendThread.isNull()) {
        if (m_sendThread->joinable()) {
            m_sendThread->join();
        }
    }

    if (!m_recvThread.isNull()) {
        if (m_recvThread->joinable()) {
            m_recvThread->join();
        }
    }
}

MsgQueue *MsgQueue::getInstance()
{
    static MsgQueue instance;
    return &instance;
}

void MsgQueue::appendModuleData(const QVariantMap& vMap)
{
    if (m_sendThread.isNull()) {
        m_sendThread = QSharedPointer<std::thread>(new std::thread(&MsgQueue::sendData, this));
    }

    QMutexLocker locker(&m_sendMutex);
    m_sendList.append(vMap);
}

// 发送数据
void MsgQueue::sendData()
{
    while (flag) {
        QVariantMap vMap;
        if (m_sendList.isEmpty()) {
            QThread::msleep(10);
            continue;
        } else {
            QMutexLocker locker(&m_sendMutex);
            vMap = m_sendList.takeFirst();
        }

        // 下发消息
        QJsonObject jsObj = QJsonObject::fromVariantMap(vMap);
        pushCmdToSlave(jsObj);
    }
}

// 接收数据
void MsgQueue::recvData()
{
    QVariantMap vMap;
    while (flag) {
        QThread::msleep(10);
        vMap = getReceiveCmd();
        if (vMap.isEmpty()) {
            continue;
        }

        emit sig_recvCmd(vMap);
    }
}

void MsgQueue::pushCmdToSlave(QJsonObject jsObj)
{
    QByteArray posixmsg = QJsonDocument(jsObj).toJson();
    qDebug().noquote()<<"____Send__MsgQueue___"<<posixmsg;
    int ret = mq_send(msg_qt_to_com, posixmsg.data(), posixmsg.size(),0);
    if (ret < 0) {
        QString errMsg = strerror(errno);
        int command = jsObj.toVariantMap().value("command").toInt();
        QString errStr = QString("qt to com failed, by result: %1, Command: %2, MsgLen: %3, Errno: %4, ErrMsg: %5").
                arg(ret).arg(command).arg(posixmsg.size()).arg(errno).arg(errMsg);
        qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<errStr;
        return;
    }
}

QVariantMap MsgQueue::getReceiveCmd()
{
    // 获取消息进程消息
    QVariantMap recvMap;
    struct mq_attr attr;
    if (msg_com_to_qt < 0) {
        return recvMap;
    } else {
        mq_getattr(msg_com_to_qt, &attr);
    }

    // 智能指针
    QScopedPointer<char> recv(new char[attr.mq_msgsize]);
    memset(recv.data(), 0, attr.mq_msgsize);
    ssize_t readposix = mq_receive(msg_com_to_qt,recv.data(),attr.mq_msgsize,NULL);
    if (readposix < 0) {
        return recvMap;
    }

    QByteArray replyByteArray(recv.data());
    QJsonParseError jsonError;
    QJsonDocument jsonDouc = QJsonDocument::fromJson(replyByteArray, &jsonError);
    if (jsonDouc.isObject()) {
        qDebug().noquote()<<"_____Rev__MsgQueue____"<<jsonDouc.toJson(QJsonDocument::Indented);
        QJsonObject jsonObj = jsonDouc.object();
        recvMap = jsonObj.toVariantMap();
        return recvMap;
    } else {
        qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<"com to qt data is not Json"<<jsonError.errorString();
    }

    return recvMap;
}

void MsgQueue::initMsgQueue()
{
    struct mq_attr attr_posix;
    attr_posix.mq_flags = 0;
    attr_posix.mq_maxmsg = 10;
    attr_posix.mq_msgsize = 2048;
    attr_posix.mq_curmsgs = 0;

    msg_qt_to_com = mq_open(COMM_UIB_QT_TO_COM_NAME, O_RDWR|O_NONBLOCK|O_CREAT, 0644, &attr_posix);
    if (msg_qt_to_com < 0) {
        QString errStr = QString("Qt mq_open %1 failed!, errnoStr = %2").arg(COMM_UIB_QT_TO_COM_NAME).arg(strerror(errno));
        qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<errStr;
        return;
    }

    msg_com_to_qt = mq_open(COMM_UIB_COM_TO_QT_NAME, O_RDWR|O_NONBLOCK|O_CREAT, 0644, &attr_posix);
    if (msg_com_to_qt < 0) {
        QString errStr = QString("Qt mq_open %1 failed!, errnoStr = %2").arg(COMM_UIB_COM_TO_QT_NAME).arg(strerror(errno));
        qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<errStr;
        return;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值