OpenDDS 3.16发布订阅简单实现

2023-11-27 13:50

本文主要是介绍OpenDDS 3.16发布订阅简单实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

OpenDDS 3.16发布订阅简单实现

      • 简介
      • 运行前提
    • 一,编译
      • 1.1 新建订阅信息文件
      • 1.2 编译idl
        • 1.2.1 目录切换
        • 1.2.2 执行命令"tao_idl Messenger.idl"
        • 1.2.3 执行命令“opendds_idl Messenger.idl”
        • 1.2.4 新建文件Messenger.mpc 内容如下所示
        • 1.2.5 执行命令生成解决方案
        • 1.2.6 编译代码
    • 二,发布端实现
      • 2.1 修改mpc文件追加如下内容
      • 2.2 使用perl 命令重新编译
      • 2.3 打开解决方案修改Publisher.cpp
      • 2.4 创建参与者
      • 2.5 注册数据类型并创建主题
      • 2.6 创建发布者
      • 2.7 创建数据写入者
      • 2.8 定义并发送数据
      • 2.9 关闭
    • 三,订阅端实现
      • 3.1 修改Mpc文件追加订阅端内容
      • 3.2 手动新建Subscriber.cpp文件
      • 3.3 拷贝接口文件到文件夹底下
      • 3.4 使用Perl命令编译
      • 3.5 重新打开解决方案并修改subscriber.cpp文件
      • 3.6 创建参与者
      • 3.7 注册类型并创建主题
      • 3.8 创建订阅者
      • 3.9 创建监听者
      • 3.10 创建数据读者
      • 3.11 用完关闭
      • 3.12 编译代码
    • 四 运行

简介

本文主要是依靠opendds3.16的samples中的发布订阅修改的代码并编译运行,如果大家对我的代码有异议或者有什么看不懂的地方,可以从opendds源码目录中的
“OpenDDS-3.16\examples\DCPS\Messenger_Imr” 文件夹中的发布订阅以及其它定义的接口实现。

运行前提

OpenDDS本地安装成功,且安装好strawberry perl并配置好各种环境变量,关于opendds的安装配置我会重写一篇文章来介绍我踩的坑及安装配置步骤。有需要的可以先在下方留言。

一,编译

1.1 新建订阅信息文件

新建一个文件我们将其命名为Messenger.idl,复制如下内容到文件中并保存。

module Messenger{#pragma DCPS_DATA_TYPE "Messenger::Message"
#pragma DCPS_DATA_KEY "Messenger::Message subject_id"struct Message{string from;string subject;long subject_id;string text;long count;};
};

1.2 编译idl

打开vs2019 命令行,并切换到刚才创建的Messenger.idl目录当中:

1.2.1 目录切换

输入命令切换到测试文件夹路径下在这里插入图片描述

1.2.2 执行命令"tao_idl Messenger.idl"

在这里插入图片描述
可以看到,多出来五个文件
在这里插入图片描述

1.2.3 执行命令“opendds_idl Messenger.idl”

在这里插入图片描述
可以看到,出了一个警告,无视即可,完事之后会出现三个新文件
在这里插入图片描述

1.2.4 新建文件Messenger.mpc 内容如下所示
project(*idl):dcps{TypeSupport_Files{Messenger.idl}custom_only = 1
}

在这里插入图片描述

1.2.5 执行命令生成解决方案
perl D:\OpenDDS\OpenDDS-3.16\ACE_wrappers\MPC\mwc.pl -type vs2019

这里面的路径自己根据自己的opendds的路径修改下
编译结果:
在这里插入图片描述
在这里插入图片描述
这里生成了我们的解决方案。

1.2.6 编译代码

使用vs2019打开项目点击生成编译代码
在这里插入图片描述
提示成功后,我们的准备阶段就做好了,下一步开始我们的发布端的实现。

二,发布端实现

2.1 修改mpc文件追加如下内容

project(*Publisher):dcpsexe,dcps_tcp{exename = publisherafter += *idlTypeSupport_Files{Messenger.idl}Source_Files{Publisher.cpp}
}

修改后的文件如下:
在这里插入图片描述
然后我们在文件夹下新建“Publisher.cpp”文件

2.2 使用perl 命令重新编译

perl D:\OpenDDS\OpenDDS-3.16\ACE_wrappers\MPC\mwc.pl -type vs2019

2.3 打开解决方案修改Publisher.cpp

引入需要的头文件及写一下main函数

#include "MessengerTypeSupportImpl.h"
#include <dds/DCPS/Service_Participant.h>
#include <dds/DCPS/Marked_Default_Qos.h>
#include <dds/DCPS/PublisherImpl.h>
#include <dds/DCPS/transport/tcp/TcpInst.h>#include "dds/DCPS/StaticIncludes.h"#include <ace/streams.h>
#include "ace/Get_Opt.h"
#include "ace/OS_NS_unistd.h"using namespace Messenger;int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) {
}

2.4 创建参与者

main函数中加入如下代码

//创建参与者
DDS::DomainParticipantFactory_var dpf =TheParticipantFactoryWithArgs(argc, argv);DDS::DomainParticipant_var participant =dpf->create_participant(111, // domain id  发布者与订阅者需要统一PARTICIPANT_QOS_DEFAULT,  //默认QoS策略DDS::DomainParticipantListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil(participant.in())) {cerr << "create_participant failed." << endl;return 1;}

2.5 注册数据类型并创建主题

MessageTypeSupportImpl* servant = new MessageTypeSupportImpl();OpenDDS::DCPS::LocalObject_var safe_servant = servant;if (DDS::RETCODE_OK != servant->register_type(participant.in(), "")) {cerr << "register_type failed." << endl;exit(1);}CORBA::String_var type_name = servant->get_type_name();//创建主题DDS::TopicQos topic_qos;participant->get_default_topic_qos(topic_qos);DDS::Topic_var topic =participant->create_topic("Wang Xiang Long",  //主题名称,自己定义type_name.in(),topic_qos,DDS::TopicListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil(topic.in())) {cerr << "create_topic failed." << endl;exit(1);}

2.6 创建发布者

//创建发布者DDS::Publisher_var pub =participant->create_publisher(PUBLISHER_QOS_DEFAULT,DDS::PublisherListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil(pub.in())) {cerr << "create_publisher failed." << endl;exit(1);}

2.7 创建数据写入者

		//创建数据写入者DDS::DataWriterQos dw_qos;pub->get_default_datawriter_qos(dw_qos);DDS::DataWriter_var dw =pub->create_datawriter(topic.in(),dw_qos,DDS::DataWriterListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil(dw.in())) {cerr << "create_datawriter failed." << endl;exit(1);}Messenger::MessageDataWriter_var message_writer = Messenger::MessageDataWriter::_narrow(dw);

2.8 定义并发送数据

		//自定义数据Messenger::Message msg;msg.subject_id = 99;msg.from = "Wang xianglong";msg.text = "AAAAAAAA";msg.subject = "publish";msg.count = 0;//发送数据for (int i = 0; i < 10; i++) {DDS::ReturnCode_t error = message_writer->write(msg, DDS::HANDLE_NIL);++msg.count;++msg.subject_id;if (error != DDS::RETCODE_OK) {return 1;}}

2.9 关闭

发送完毕之后删除掉创建的参与者等

participant->delete_contained_entities();
dpf->delete_participant(participant.in());
TheServiceParticipant->shutdown();
return 0;

如上,main函数内的方法写完了
在这里插入图片描述
点击生成编译代码。

ok这样我们的发布端就算完成了,检查下文件夹中出现如下内容代表成功了
在这里插入图片描述

三,订阅端实现

3.1 修改Mpc文件追加订阅端内容

project(*Subscriber):dcpsexe,dcps_tcp{exename = subscriberafter += *idlTypeSupport_Files{Messenger.idl}Source_Files{subscriber.cppDataReaderListener.cpp}
}

参考如下图:
在这里插入图片描述

3.2 手动新建Subscriber.cpp文件

3.3 拷贝接口文件到文件夹底下

在这里插入图片描述
将如上两个文件复制到我们测试的文件夹底下

3.4 使用Perl命令编译

命令行输入命令:

perl D:\OpenDDS\OpenDDS-3.16\ACE_wrappers\MPC\mwc.pl -type vs2019

3.5 重新打开解决方案并修改subscriber.cpp文件

在文件中先写好头文件及需要的main方法

#include "DataReaderListener.h"
#include "MessengerTypeSupportImpl.h"
#include <dds/DCPS/Service_Participant.h>
#include <dds/DCPS/Marked_Default_Qos.h>
#include <dds/DCPS/SubscriberImpl.h>
#include <dds/DCPS/transport/tcp/TcpInst.h>
#include "dds/DCPS/StaticIncludes.h"#include <ace/streams.h>
#include "ace/Get_Opt.h"
#include "ace/OS_NS_unistd.h"using namespace Messenger;int ACE_TMAIN(int argc, ACE_TCHAR* argv[])
{}

3.6 创建参与者

//创建参与者
DDS::DomainParticipantFactory_var dpf;
DDS::DomainParticipant_var participant;dpf = TheParticipantFactoryWithArgs(argc, argv);
participant = dpf->create_participant(111,  //domain id 发布订阅要同步PARTICIPANT_QOS_DEFAULT,  //使用默认QoS策略DDS::DomainParticipantListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
if (CORBA::is_nil (participant.in ())) {cerr << "create_participant failed." << endl;return 1 ;
}

3.7 注册类型并创建主题

//注册类型
MessageTypeSupportImpl* mts_servant = new MessageTypeSupportImpl();
OpenDDS::DCPS::LocalObject_var safe_servant = mts_servant;if (DDS::RETCODE_OK != mts_servant->register_type(participant.in (), "")) {cerr << "Failed to register the MessageTypeTypeSupport." << endl;exit(1);}CORBA::String_var type_name = mts_servant->get_type_name ();
//创建主题
DDS::TopicQos topic_qos;
participant->get_default_topic_qos(topic_qos);
DDS::Topic_var topic = participant->create_topic("Wang Xiang Long", // 主题名称与发布端保持一致type_name.in (),topic_qos,DDS::TopicListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
if (CORBA::is_nil (topic.in ())) {cerr << "Failed to create_topic." << endl;exit(1);
}

3.8 创建订阅者

// Create the subscriber
DDS::Subscriber_var sub =participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT,DDS::SubscriberListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
if (CORBA::is_nil (sub.in ())) {cerr << "Failed to create_subscriber." << endl;exit(1);
}

3.9 创建监听者

DataReaderListenerImpl 这个类是我们第三步中从opendds的测试目录中拿来的代码,这个类重写了DataReaderListener 类的方法,实现了监听数据并打印的功能,如果我们订阅主题的数据发生变化,可以修改这个监听类中的方法解析数据

     // 激活监听者DDS::DataReaderListener_var listener (new DataReaderListenerImpl);DataReaderListenerImpl* listener_servant =dynamic_cast<DataReaderListenerImpl*>(listener.in());if (CORBA::is_nil (listener.in ())) {cerr << "listener is nil." << endl;exit(1);}if (!listener_servant) {ACE_ERROR_RETURN((LM_ERROR,ACE_TEXT("%N:%l main()")ACE_TEXT(" ERROR: listener_servant is nil (dynamic_cast failed)!\n")), -1);}

3.10 创建数据读者

	// Create the DatareadersDDS::DataReaderQos dr_qos;sub->get_default_datareader_qos (dr_qos);DDS::DataReader_var dr = sub->create_datareader(topic.in (),dr_qos,listener.in (),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil (dr.in ())) {cerr << "create_datareader failed." << endl;exit(1);}int expected = 10;while ( listener_servant->num_reads() < expected) {ACE_OS::sleep (1);}

在这一步中通过DataReaderListenerImpl 中的on_data_available方法对收到的数据进行监听打印输出

3.11 用完关闭

	  if (!CORBA::is_nil (participant.in ())) {participant->delete_contained_entities();}if (!CORBA::is_nil (dpf.in ())) {dpf->delete_participant(participant.in ());}ACE_OS::sleep(2);TheServiceParticipant->shutdown();

3.12 编译代码

编译成功后我们的文件夹底下出现了如下文件
在这里插入图片描述

四 运行

我这边测试运行的时候使用了ini文件辅助执行
各位可以把这个目录下的这两个文件复制到测试的文件夹下
在这里插入图片描述
在这里插入图片描述
1,打开一个vs的命令行工具输入

DCPSInfoRepo -ORBListenEndPoints iiop://localhost:12345

在这里插入图片描述
2,再打开一个命令行工具切换到测试路径下输入订阅命令

.\Subscriber -DCPSInfoRepo corbaloc::localhost:12345/DCPSInfoRepo -DCPSConfigFile sub.ini

结果如下:
在这里插入图片描述
3,再开启一个命令行切换到测试路径下,输入发布命令

.\Publisher -DCPSInfoRepo corbaloc::localhost:12345/DCPSInfoRepo -DCPSConfigFile pub.ini

结果如下:
在这里插入图片描述
个人建议一定要用管理员身份打开命令行运行,不然会没反应。

这篇关于OpenDDS 3.16发布订阅简单实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/427793

相关文章

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

java如何分布式锁实现和选型

《java如何分布式锁实现和选型》文章介绍了分布式锁的重要性以及在分布式系统中常见的问题和需求,它详细阐述了如何使用分布式锁来确保数据的一致性和系统的高可用性,文章还提供了基于数据库、Redis和Zo... 目录引言:分布式锁的重要性与分布式系统中的常见问题和需求分布式锁的重要性分布式系统中常见的问题和需求

SpringBoot基于MyBatis-Plus实现Lambda Query查询的示例代码

《SpringBoot基于MyBatis-Plus实现LambdaQuery查询的示例代码》MyBatis-Plus是MyBatis的增强工具,简化了数据库操作,并提高了开发效率,它提供了多种查询方... 目录引言基础环境配置依赖配置(Maven)application.yml 配置表结构设计demo_st

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

Python pyinstaller实现图形化打包工具

《Pythonpyinstaller实现图形化打包工具》:本文主要介绍一个使用PythonPYQT5制作的关于pyinstaller打包工具,代替传统的cmd黑窗口模式打包页面,实现更快捷方便的... 目录1.简介2.运行效果3.相关源码1.简介一个使用python PYQT5制作的关于pyinstall

使用Python实现大文件切片上传及断点续传的方法

《使用Python实现大文件切片上传及断点续传的方法》本文介绍了使用Python实现大文件切片上传及断点续传的方法,包括功能模块划分(获取上传文件接口状态、临时文件夹状态信息、切片上传、切片合并)、整... 目录概要整体架构流程技术细节获取上传文件状态接口获取临时文件夹状态信息接口切片上传功能文件合并功能小

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur