使用Qt Remote Objects 编写一个简单的文件读写代理

Qt Remote Objects 是一个基于进程通信的机制,让开发人员调用一个其他进程的方法就像本地调用一样。这里我写一个简单的样例,主要是能够在进程A写入数据,但实际上是进程B写入文件数据。这样子的方式,让开发者写代码就像没有网络或者管道一样。

cmake添加字段

find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets RemoteObjects)

此处引用了qt的对应模块

添加Qt指定的接口模板

file(GLOB REPSOURCE APPEND "*.rep" )

#用于建立服务端,自动编译生成节点功能模板

qt6_add_repc_sources(SourceNode

${REPSOURCE}

)

#用于客户端,实际使用者,自动生成节点代理

qt6_add_repc_replicas(SourceNode

${REPSOURCE}

)

上面两个也可以合成一段cmake,qt文档里面有对应的cmake方法。

链接对应的库

target_link_libraries(SourceNode PRIVATE

Qt${QT_VERSION_MAJOR}::Widgets

Qt6::RemoteObjects

)

Node01.rep

class Node01
{
    PROP(bool actived=false);
    SLOT(server_slot(bool state));
    SLOT(writeFile(const QString&,const QByteArray&));
    SIGNAL(message(const QString&));
}

上述actived只是为了测试信号是否有效。

server_slot只是为了测试槽函数是否正确链接

writeFile 是真正的跨进程写文件

message 只是为了方便的显示日志

Node01Impl.cpp

文件是作为实际提供写功能的服务端代码。

按照qt的rep接口要求,自动生成的rep_Node01_source.h定义了需要实现的接口(纯虚函数)

writeFile 需要作为槽函数实现写文件功能

void Node01Impl::writeFile(const QString &fileName, const QByteArray &__repc_variable_2)
{
    auto fileP = mFiles.value(fileName);
    if(fileP==nullptr)
    {
        fileP.reset(new QFile(fileName));
        mFiles.insert(fileName,fileP);
    }

    if(!fileP->isOpen())
    {
        auto ret  = fileP->open(QIODevice::WriteOnly);
        if(!ret)
        {
            return ;
        }
    }

    if(__repc_variable_2.isEmpty())
    {

        fileP->close();
        mFiles.remove(fileName);
        return ;
    }


    fileP->write(__repc_variable_2);
    qDebug()<<" write "<<fileName <<" msg "<<__repc_variable_2;
    return ;

}

上述代码效率不高,仅仅是为了实现测试效果,实际使用应该是单例文件管理,不去判断过多。

代码简单的实现了创建文件,在发送过来的信息是空的时候,关闭并且结束文件控制。

实际使用:

  1. 进程A,创建服务,可以理解为建立一个tcpserver,发布一个节点,提供大家功能

void MainWindow::on_pushButton_2_clicked()
{
    //注册一个服务集群,提供路由管理调用
    if(registry==nullptr)
    {
        registry= new QRemoteObjectRegistryHost(registerUrl,this);
        registry->setName("vvvv");
    }

    //创建服务,并且注册到指定的集群
    if(mHost==nullptr)
    {
        mHost = new QRemoteObjectHost(hostUrl,registerUrl);
        mHost->setName("zzc");
    }

    //创建我的服务
    if(mNode1==nullptr)
    {
        mNode1 = new Node01Impl(this);
    }
    mHost->enableRemoting(mNode1,"node1222");
    registry->enableRemoting(mNode1,"node001");

}

上述代码,建立了一个服务,把之前的rep中实现的功能对象注册,也就是,如果其他进程找到了我注册对象,就可以使用它的函数。

  1. 进程B,查找服务,可以理解为tcp尝试去和服务器连接,找到之前注册的服务。并且创建他们之间的代理对象(不需要我们关心是断开了)

//connect 创建一个用户节点,准备调用远端的方法

    if(repNode==nullptr)
    {
        //连结集群服务
        repNode = new QRemoteObjectNode(registerUrl, this);
         //repNode = new QRemoteObjectNode( this);
        //连结指定地址服务,上面构造如果注册节点有效,此处可以不需要
        repNode->connectToNode(hostUrl);
        repNode->setName("clientNode");
        //此处如果不等待,下面立即获取实力可能是会失败的
        repNode->waitForRegistry();
    }

    QStringList ins;
    ins<<" instaces :"<<repNode->instances<Node01Replica>();
    ui->textBrowser->append(ins.join(" "));
    if(nodePtr==nullptr)
    {
        //获取服务,使用服务,node001,node1222获取到的都是同一个对象,只是注册的名称不一样
        nodePtr.reset(repNode->acquire<Node01Replica>("node001"));
        auto dyn = repNode->acquireDynamic("node001");
        if(dyn)
        {
             connect(dyn,SIGNAL(message(const QString&)),this,SLOT(messageLog(const QString &)));
            qDebug()<<" dynamic get";
        }
        connect(nodePtr.data(),&Node01Replica::activedChanged,this,[this](){

            qDebug()<<" state changed "<<this->nodePtr->actived();
            ui->textBrowser->append(" state changed " +QString(this->nodePtr->actived()?" actived ":" inactived"));
        });


    }

    //简单测试目标节点的功能是否可用
    this->nodePtr->server_slot(false);

上述代码有少量测试逻辑,不影响整体流程。但是注意waitForRegistry是否需要取决于你是否会立即想调用远端的功能。因为后面我需要测试instances是否存在,所以会需要。实际测试,第一次调用这个函数,得到一个节点,第二次以后有两个(这个是正确的),所以链接建立是有延迟的。

  1. 进程B,尝试开始写文件


    for(int i=0;i<1000;++i)
    {
        auto msg =  "message "+ QByteArray::number(i)+"\n";
        this->nodePtr->writeFile("./testfile.txt",msg);
    }
    this->nodePtr->writeFile("./testfile.txt","");

逻辑很简单,就是直接调用代理的函数。

测试,左边的app,按server建立服务,右边依次按connect和write to,写数据。

在左边的程序路径下,得到测试文件。

源码等待上传,使用的QT为6.3.2

源码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值