OpenDDS 跨主机通信配置与实现(C++和Java)

目录

  • 1、编写一个示例
    • 1.1、IDL接口定义
    • 1.2、MPC文件介绍
    • 1.3、生成解决方案
  • 2、通讯测试
    • 2.1、使用repo server 通讯
    • 2.2、使用repo ip+port方式
    • 2.3、对等发现face

1、编写一个示例

1.1、IDL接口定义

假设我们现在有以下结构:

struct MessagerOne
{
int subject_id;
string time;
string text;
int index;
double start Counter;
double frequency;};
struct Heartbeat
{int use_id;int index;};

那么我们将其编写为idl格式,文件名为DDSData.h,文件内容为:

module DDSData{@topicstruct MessagerOne{@key long subject_id;string time;string text;long index;double startCounter;double frequency;};	@topicstruct Heartbeat{@key long use_id;long index;};
};

然后生成DDSData _Export.h文件: 此处的名称规则为DDSData _Export.h

perl D:\OpenDDS\ACE_wrappers\bin\generate_export_file.pl DDSData > DDSData_Export.h

生成的文件内容:
在这里插入图片描述

1.2、MPC文件介绍

dcps 项目就是用来生成动态库的,dcps_java项目是用于生成jar包的,另外俩个项目就是一个简易的订阅/发布例子。
这里缺少 Publisher.cpp、 Subscriber.cpp、DataReaderListenerImpl.cpp、DataReaderListenerImpl.h四个文件,后面会贴出代码。

project(*idl): dcps {requires += no_opendds_safety_profileTypeSupport_Files {DDSData.idl}custom_only = 1
}project(*java): dcps_java {idlflags      += -Wb,stub_export_include=DDSData_Export.h \-Wb,stub_export_macro=DDSData_Exportdcps_ts_flags += -Wb,export_export_include=DDSData_Export.h \-Wb,export_export_macro=DDSData_Exportidl2jniflags  += -Wb,stub_export_include=DDSData_Export.h \-Wb,stub_export_macro=DDSData_Exportdynamicflags  += DDSDATA_BUILD_DLLTypeSupport_Files {DDSData.idl}specific{jarname = DDSData}Source_Files {}
}project(*publisher) : dcpsexe, dcps_tcp, dcps_rtps_udp {requires += no_opendds_safety_profileexename   = publisherafter    += *idlTypeSupport_Files {DDSData.idl}Source_Files {Publisher.cpp}
}project(*subscriber) : dcpsexe, dcps_tcp, dcps_rtps_udp {requires += no_opendds_safety_profileexename   = subscriberafter    += *publisherTypeSupport_Files {DDSData.idl}Source_Files {DataReaderListenerImpl.cppSubscriber.cpp}
}

Publisher.cpp

#include "DDSData_TS.hpp"
#include "ace/Log_Msg.h"
#include "ace/OS_NS_unistd.h"#ifdef ACE_AS_STATIC_LIBS
# include "dds/DCPS/RTPS/RtpsDiscovery.h"
# include "dds/DCPS/transport/rtps_udp/RtpsUdp.h"
#endif// FUZZ: disable check_for_improper_main_declaration
int main(int, char*[])
{// Initialize the TS interfaceFACE::RETURN_CODE_TYPE status;FACE::TS::Initialize("face_config.ini", status);if (status != FACE::RC_NO_ERROR) {return static_cast<int>(status);}// Create the pub connectionFACE::CONNECTION_ID_TYPE connId;FACE::CONNECTION_DIRECTION_TYPE dir;FACE::MESSAGE_SIZE_TYPE max_msg_size;FACE::TS::Create_Connection("pub", FACE::PUB_SUB, connId, dir,max_msg_size, FACE::INF_TIME_VALUE, status);if (status != FACE::RC_NO_ERROR) {return static_cast<int>(status);}// Message to sendMessenger::Message msg;msg.text = "Hello, World!";msg.subject_id = 14;msg.count = 1;// Send messageFACE::TRANSACTION_ID_TYPE txn;ACE_DEBUG((LM_INFO, "Publisher: about to Send_Message()\n"));FACE::TS::Send_Message(connId, FACE::INF_TIME_VALUE, txn, msg,max_msg_size, status);if (status != FACE::RC_NO_ERROR) {return static_cast<int>(status);}// Give message time to be processed before exitingACE_OS::sleep(15);// Destroy the pub connectionFACE::TS::Destroy_Connection(connId, status);if (status != FACE::RC_NO_ERROR) {return static_cast<int>(status);}return EXIT_SUCCESS;
}
// FUZZ: enable check_for_improper_main_declaration

Subscriber.cpp

#include "DDSData_TS.hpp"
#include "ace/Log_Msg.h"#ifdef ACE_AS_STATIC_LIBS
# include "dds/DCPS/RTPS/RtpsDiscovery.h"
# include "dds/DCPS/transport/rtps_udp/RtpsUdp.h"
#endif// FUZZ: disable check_for_improper_main_declaration
int main(int, char*[])
{// Initialize the TS interfaceFACE::RETURN_CODE_TYPE status;FACE::TS::Initialize("face_config.ini", status);if (status != FACE::RC_NO_ERROR) {return static_cast<int>(status);}// Create the sub connectionFACE::CONNECTION_ID_TYPE connId;FACE::CONNECTION_DIRECTION_TYPE dir;FACE::MESSAGE_SIZE_TYPE max_msg_size;FACE::TS::Create_Connection("sub", FACE::PUB_SUB, connId, dir,max_msg_size, FACE::INF_TIME_VALUE, status);if (status != FACE::RC_NO_ERROR) {return static_cast<int>(status);}// Receive a messageconst FACE::TIMEOUT_TYPE timeout = FACE::INF_TIME_VALUE;FACE::TRANSACTION_ID_TYPE txn;Messenger::Message msg;ACE_DEBUG((LM_INFO, "Subscriber: about to Receive_Message()\n"));FACE::TS::Receive_Message(connId, timeout, txn, msg, max_msg_size, status);if (status != FACE::RC_NO_ERROR) {return static_cast<int>(status);}// Output the messageACE_DEBUG((LM_INFO, "%C\t%d\n", msg.text.in(), msg.count));// Destroy the sub connectionFACE::TS::Destroy_Connection(connId, status);if (status != FACE::RC_NO_ERROR) {return static_cast<int>(status);}return EXIT_SUCCESS;
}
// FUZZ: enable check_for_improper_main_declaration

DataReaderListenerImpl.h

#ifndef DATAREADER_LISTENER_IMPL_H
#define DATAREADER_LISTENER_IMPL_H#include <ace/Global_Macros.h>#include <dds/DdsDcpsSubscriptionC.h>
#include <dds/DCPS/LocalObject.h>
#include <dds/DCPS/Definitions.h>class DataReaderListenerImpl: public virtual OpenDDS::DCPS::LocalObject<DDS::DataReaderListener> {
public:virtual void on_requested_deadline_missed(DDS::DataReader_ptr reader,const DDS::RequestedDeadlineMissedStatus& status);virtual void on_requested_incompatible_qos(DDS::DataReader_ptr reader,const DDS::RequestedIncompatibleQosStatus& status);virtual void on_sample_rejected(DDS::DataReader_ptr reader,const DDS::SampleRejectedStatus& status);virtual void on_liveliness_changed(DDS::DataReader_ptr reader,const DDS::LivelinessChangedStatus& status);virtual void on_data_available(DDS::DataReader_ptr reader);virtual void on_subscription_matched(DDS::DataReader_ptr reader,const DDS::SubscriptionMatchedStatus& status);virtual void on_sample_lost(DDS::DataReader_ptr reader,const DDS::SampleLostStatus& status);
};#endif /* DATAREADER_LISTENER_IMPL_H */

DataReaderListenerImpl.cpp

#include <ace/Log_Msg.h>
#include <ace/OS_NS_stdlib.h>#include "DataReaderListenerImpl.h"
#include "MessengerTypeSupportC.h"
#include "MessengerTypeSupportImpl.h"#include <iostream>void
DataReaderListenerImpl::on_requested_deadline_missed(DDS::DataReader_ptr /*reader*/,const DDS::RequestedDeadlineMissedStatus& /*status*/)
{
}void
DataReaderListenerImpl::on_requested_incompatible_qos(DDS::DataReader_ptr /*reader*/,const DDS::RequestedIncompatibleQosStatus& /*status*/)
{
}void
DataReaderListenerImpl::on_sample_rejected(DDS::DataReader_ptr /*reader*/,const DDS::SampleRejectedStatus& /*status*/)
{
}void
DataReaderListenerImpl::on_liveliness_changed(DDS::DataReader_ptr /*reader*/,const DDS::LivelinessChangedStatus& /*status*/)
{
}void
DataReaderListenerImpl::on_data_available(DDS::DataReader_ptr reader)
{Messenger::MessageDataReader_var reader_i =Messenger::MessageDataReader::_narrow(reader);if (!reader_i) {ACE_ERROR((LM_ERROR,ACE_TEXT("ERROR: %N:%l: on_data_available() -")ACE_TEXT(" _narrow failed!\n")));ACE_OS::exit(1);}Messenger::Message message;DDS::SampleInfo info;const DDS::ReturnCode_t error = reader_i->take_next_sample(message, info);if (error == DDS::RETCODE_OK) {std::cout << "SampleInfo.sample_rank = " << info.sample_rank << std::endl;std::cout << "SampleInfo.instance_state = " << OpenDDS::DCPS::InstanceState::instance_state_mask_string(info.instance_state) << std::endl;if (info.valid_data) {// 数据的输出  取决于你的IDL定义 std::cout << "Message: subject    = " << message.subject.in() << std::endl<< "         subject_id = " << message.subject_id   << std::endl<< "         from       = " << message.from.in()    << std::endl<< "         count      = " << message.count        << std::endl<< "         text       = " << message.text.in()    << std::endl;}} else {ACE_ERROR((LM_ERROR,ACE_TEXT("ERROR: %N:%l: on_data_available() -")ACE_TEXT(" take_next_sample failed!\n")));}
}void
DataReaderListenerImpl::on_subscription_matched(DDS::DataReader_ptr /*reader*/,const DDS::SubscriptionMatchedStatus& /*status*/)
{
}void
DataReaderListenerImpl::on_sample_lost(DDS::DataReader_ptr /*reader*/,const DDS::SampleLostStatus& /*status*/)
{
}

1.3、生成解决方案

通过mwc生成vs解决方案

perl D:\OpenDDS\ACE_wrappers\bin\mwc.pl -type vs2019  -features java=1

生成后如下图所示:(文件名称忽略掉,不是一个工程)
在这里插入图片描述
打开*.sln,编译Messenger_Idl工程,无报错说明C++端的已生成成功。编译Messenger_Java工程,无报错说明java端的已生成成功。

2、通讯测试

2.1、使用repo server 通讯

运行程序DCPSInfoRepo,subscriber,publisher;
先在A机器上运行DCPSInfoRepo和subscriber;然后在B机器上运行publisher。
(1)A机器上先运行&DDS_ROOT/bin/DCPSInfoRepo-ORBDebugLevel 10 -ORBLogFile DCPSInfoRepo.log -o repo.ior;
(2)拷贝A机器上repo.ior文件到B机器上;
(3)A机器上运行./subscriber -ORBDebugLevel 10 -DCPSDebugLevel 10 – DCPSTransportDebugLevel 6 -ORBLogFile subscriber.log
(4)B机器上运行./publisher -ORBDebugLevel 10 -DCPSDebugLevel 10 – ORBLogFile publisher.log

注意事项:
(1) DCPSInfoRepo生成的repo.ior文件必须存放在subscriber和publisher工程文件目录下;
(2) 必须先运行DCPSInfoRepo,然后拷贝repo.ior文件到其他机器上;

rtps.ini文件内容(DCPSInfoRepo后面的路径为你的实际路径)

[common]
DCPSInfoRepo=file://D:\OpenDDS\DevGuideExamples\DCPS\Messenger\repo.ior[transport/1]
transport_type=tcp

2.2、使用repo ip+port方式

运行程序DCPSInfoRepo,subscriber,publisher;
先在A机器上运行DCPSInfoRepo和subscriber;然后在B机器上运行publisher。

DCPSInfoRepo:
DCPSInfoRepo -ORBListenEndpoints iiop://192.168.175.135:12345 -ORBDebugLevel 10 -ORBLogFile DCPSInfoRepo.log

subscriber订阅:
.\subscriber.exe -DCPSConfigFile rtps.ini

publisher发布:
.\publisher.exe -DCPSConfigFile rtps.ini

rtps.ini文件内容

[common]
DCPSDebugLevel=0
DCPSInfoRepo=corbaloc::192.168.0.11:12345/DCPSInfoRepo
DCPSChunks=20
DCPSChunkAssociationMutltiplier=10
DCPSLivelinessFactor=80
DCPSBit=0
DCPSGlobalTransportConfig=$file[domain/42]
DiscoveryConfig=uni_rtps[rtps_discovery/uni_rtps]
SedpMulticast=0
ResendPeriod=2[transport/the_rtps_transport]
transport_type=rtps_udp
use_multicast=0[topic/Message]
platform_view_guid=103
type_name=DDSData::MessageOne
max_message_size=300

2.3、对等发现face

运行程序subscriber,publisher;
先在A机器上运行subscriber;然后在B机器上运行publisher。

rtps.ini文件内容

[common]
DCPSGlobalTransportConfig=$file
DCPSDefaultDiscovery=DEFAULT_RTPS[domain/3]
DiscoveryConfig=uni_rtps[rtps_discovery/uni_rtps]
SedpMulticast=0
ResendPeriod=2[transport/the_rtps_transport]
transport_type=rtps_udp
use_multicast=0[topic/Message]
platform_view_guid=103
type_name=DDSData::MessageOne
max_message_size=300

关于Java端的代码具体可参考OpenDDS\java\tests\messenger下的demo。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/269142.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CMU 10-414/714: Deep Learning Systems --hw0

hw0 宏观上的步骤: softmax loss: 实现softmax loss代码 概念 softmax就是将结果映射到0~1之间,且所有结果相加为1(概率形式)cross-entropy loss就是计算 p ( x ) log ⁡ q ( x ) p(x)\log {q(x)} p(x)logq(x),此值可用于衡量实际输出与期望输出的距离,进而衡量预测模…

各种排序算法

文章目录 1. 基于比较排序算法总结2. 非比较排序算法 1. 基于比较排序算法总结 2. 非比较排序算法

路由器端口映射如何配置?

在网络通信中&#xff0c;路由器是一个重要的设备&#xff0c;它负责将数据包从一个网络传输到另一个网络。路由器的端口映射配置是一种重要的设置&#xff0c;可以使外部网络中的计算机通过访问路由器上的特定端口与内部网络中的计算机进行通信。本文将介绍什么是路由器端口映…

LabVIEW石油钻机提升系统数字孪生技术

LabVIEW石油钻机提升系统数字孪生技术 随着数字化、信息化、智能化的发展&#xff0c;石油钻采过程中的石油钻机数字化技术提升成为了提高钻井效率、降低生产成本的重要途径。基于中石油云平台提供的数据&#xff0c;采用数字孪生技术&#xff0c;对石油钻机提升系统进行数字化…

electron+vue3全家桶+vite项目搭建【29】封装窗口工具类【3】控制窗口定向移动

文章目录 引入实现效果思路声明通用的定位对象主进程模块渲染进程测试效果 引入 demo项目地址 窗口工具类系列文章&#xff1a; 封装窗口工具类【1】雏形 封装窗口工具类【2】窗口组&#xff0c;维护窗口关系 封装窗口工具类【3】控制窗口定向移动 很多时候&#xff0c;我们想…

C语言--- qsort函数

目录 一.qsort函数 1.qsort函数的功能 2.四个参数讲解 (1)base (2)num (3)size (4)compare 3.使用qsort函数对一个整形数组进行排序 4.qsort函数排序结构体数据 第一种&#xff1a;按照年龄进行比较 第二种&#xff1a;按照名字进行排序 二.利用冒泡排序模仿qsort函…

嵌入式驱动学习第二周——Linux内核打印

前言 这篇博客来聊一聊Linux内核打印。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博主并订阅本专栏&#xff0c;一起讨论一起学习。现在关注就是老粉啦&#xff01; 目录 前言1. dmesg指令…

#QT(串口助手-实现)

1.IDE&#xff1a;QTCreator 2.实验 3.记录 &#xff08;1&#xff09;在widget.h中加入必要文件&#xff0c;并且定义一个类指针 &#xff08;2&#xff09;如果有类的成员不知道怎么写&#xff0c;可以通过以下途径搜索 &#xff08;2&#xff09;设置串口数据 void Widget…

Java架构之路-架构应全面了解的技术栈和工作域

有时候我在想这么简单简单的东西&#xff0c;怎么那么难以贯通。比如作为一个架构师可能涉及的不单单是技术架构&#xff0c;还包含了项目管理&#xff0c;一套完整的技术架构也就那么几个技术栈&#xff0c;只要花点心思&#xff0c;不断的往里面憨实&#xff0c;总会学的会&a…

JavaScript基础2之运算符、函数

JavaScript基础 运算符一元操作符递增/递减一元加和减 布尔操作符逻辑非逻辑与逻辑或 乘性操作符乘法操作符除法操作符取模操作符 加性操作符加法操作符减法操作符 比较操作符相等操作符关系操作符 函数函数声明函数表达式箭头函数函数的实参和形参arguments 默认参数参数的拓展…

tomcat优化、nginx +tomcat 部署 (三)

在目前流行的互联网架构中&#xff0c;Tomcat在目前的网络编程中是举足轻重的&#xff0c;由于Tomcat的运行依赖于JVM&#xff0c;从虚拟机的角度把Tomcat的调整分为外部环境调优 JVM 和 Tomcat 自身调优两部分 Tomcat 是一个流行的开源 Java 服务器&#xff0c;用于托管 Java …

第十二届“中关村青联杯”全国研究生数学建模竞赛-A题:水面舰艇编队防空和信息化战争评估模型(续)

目录 5.5 问题五模型的建立与求解 5.5.1 战略级信息化战争评估模型 5.5.2 战略级信息化战争评估模型的验证 6. 模型的评价 6.1 模型的优点 6.2 模型的缺点 参考文献 代码实现 附件1 &#xff08;1&#xff09;No_1_result.m 源代码 &#xff08;2&#xff09;No_1_figure.m 源代…

汽车零部件制造中的信息抽取技术:提升效率与质量的关键

一、引言 在汽车制造业中&#xff0c;零部件的生产是整个制造流程的关键一环。这些零部件&#xff0c;包括但不限于制动系统、转向系统和传动系统&#xff0c;是确保汽车安全、可靠运行的基础。为了满足现代汽车工业对效率和质量的严格要求&#xff0c;制造商们纷纷投入到高度…

HarmonyOS—HAP唯一性校验逻辑

HAP是应用安装的基本单位&#xff0c;在DevEco Studio工程目录中&#xff0c;一个HAP对应一个Module。应用打包时&#xff0c;每个Module生成一个.hap文件。 应用如果包含多个Module&#xff0c;在应用市场上架时&#xff0c;会将多个.hap文件打包成一个.app文件&#xff08;称…

P-States/C-States/S-States/G-States/D-States

P-States是指处理器的性能状态&#xff0c;可以根据需要调整处理器的工作频率和电压来平衡性能和能效。 S-States是指系统的睡眠状态&#xff0c;可以让系统在空闲时进入低功耗状态以节省能量。 G-States是系统的全局状态&#xff0c;通常用于描述整个系统的运行状态。 C-St…

文件上传之图片马

图片马介绍 图片马&#xff1a;就是在正常图片中插入木马。 图片马的制作 1.我们先创建php木马文件1.php&#xff0c;内容有以下两种方式&#xff1a; <?php eval($_POST[a]); ?> /* 常规一句话木马 */ <?php $aPD9waHAgQGV2YWwoJF9QT1NUWydhJ10pOz8; $myfile…

使用Pytorch导出自定义ONNX算子

在实际部署模型时有时可能会遇到想用的算子无法导出onnx&#xff0c;但实际部署的框架是支持该算子的。此时可以通过自定义onnx算子的方式导出onnx模型&#xff08;注&#xff1a;自定义onnx算子导出onnx模型后是无法使用onnxruntime推理的&#xff09;。下面给出个具体应用中的…

重构笔记系统:Docker Compose在微服务架构中的应用与优化

虽然我的笔记系统的开发是基于微服务的思想&#xff0c;但是在服务的配置和编排上感觉还是不太合理&#xff0c;具体来说&#xff0c;在开发上的配置和在生产上的配置差别太大。现在规模小&#xff0c;后面规模变大&#xff0c;估计这一块会成为系统生长的瓶颈。 因此&#xff…

推特API(Twitter API)对接说明,用户code To Token换取

前期准备 提前准备、说明&#xff1a;目前对接推特api开发门户分为3个版本&#xff0c;分别是免费的&#xff0c;100美金一个月的基础版以及5000美金一个月的企业版&#xff0c;免费的目前就两个接口可以调用&#xff0c;所以想要对接和使用推特最基本的也需要付100美元一个月…

ETAS工具链ISOLAR-AB重要概念,RTE配置,ECU抽取

RTE配置界面&#xff0c;包含ECU抽取关联 首次配置RTE&#xff0c;出现需要勾选的抽取EXTRACT 创建System System制作SWC到ECU的Mapping System制作System Data 的Mapping