【FastDDS】Layer DDS之Domain ( 03-DomainParticipantListener)
Fast DDS 域参与者监听器(DomainParticipantListener)详解
一、域参与者监听器(DomainParticipantListener)基础定义
DomainParticipantListener
(域参与者监听器)是一个抽象类,用于定义在域参与者(DomainParticipant)状态发生变化时触发的回调函数。默认情况下,所有回调函数均为空实现,不执行任何操作。用户需实现该类的特化版本,重写应用程序所需的回调函数;未重写的回调函数将保持空实现。
DomainParticipantListener
继承自 TopicListener
(主题监听器)、PublisherListener
(发布者监听器)和 SubscriberListener
(订阅者监听器)。因此,它能够响应所有附加实体(Entities)上报的各类事件。由于事件始终会通知给能够处理该事件的“最具体实体监听器”,所以 DomainParticipantListener
从其他监听器继承的回调函数,仅在以下情况下才会被调用:没有其他实体能处理该事件(要么该实体未附加监听器,要么实体的 StatusMask
(状态掩码)禁用了该回调函数)。
二、域参与者监听器的非标准回调函数
除了从父类继承的回调函数外,DomainParticipantListener
还额外添加了以下非标准回调函数,用于处理域内实体发现、身份认证等特定事件:
(一)on_participant_discovery()
:域参与者发现回调
当同一域内发现新的域参与者、已知域参与者被移除,或某域参与者的 QoS(服务质量)发生变更时,该回调函数会被触发。
该函数提供一个重载版本,包含额外的布尔型输出参数——通过此参数,发现回调可告知中间件是否需要通过 ignore_participant()
函数忽略新发现的域参与者。若需在发现回调内部忽略域参与者,应使用该重载版本,因为在监听器中直接调用 ignore_participant()
可能导致死锁。
若同时实现了两个版本的回调函数(带布尔参数和不带布尔参数),则带有 should_be_ignored
(是否应忽略)布尔标志的版本优先级更高。只有当第一个回调函数中未忽略该域参与者(should_be_ignored
参数返回 false
)时,才会执行第二个回调函数。
(二)on_data_reader_discovery()
:数据读取器发现回调
当同一域内发现新的 DataReader
(数据读取器)、已知 DataReader
被移除,或某 DataReader
的 QoS 发生变更时,该回调函数会被触发。
(三)on_data_writer_discovery()
:数据写入器发现回调
当同一域内发现新的 DataWriter
(数据写入器)、已知 DataWriter
被移除,或某 DataWriter
的 QoS 发生变更时,该回调函数会被触发。
(四)onParticipantAuthentication()
:域参与者身份认证回调
该回调函数用于告知远程域参与者身份认证过程的结果,包括认证成功和认证失败两种情况。需注意,此回调函数仅在启用安全功能(HAVE_SECURITY
宏定义生效)时可用。
三、自定义域参与者监听器(CustomDomainParticipantListener)示例
以下是自定义 DomainParticipantListener
的完整代码示例,实现了上述所有非标准回调函数,展示了如何处理域参与者、数据读取器、数据写入器的发现事件及身份认证事件:
class CustomDomainParticipantListener : public DomainParticipantListener
{public:CustomDomainParticipantListener(): DomainParticipantListener(){}virtual ~CustomDomainParticipantListener(){}// 域参与者发现回调(带should_be_ignored参数的重载版本)void on_participant_discovery(DomainParticipant* participant,eprosima::fastdds::rtps::ParticipantDiscoveryStatus status,const ParticipantBuiltinTopicData& info,bool& should_be_ignored) override{should_be_ignored = false; // 默认不忽略新发现的域参与者// 处理“发现新域参与者”事件if (status == eprosima::fastdds::rtps::ParticipantDiscoveryStatus::DISCOVERED_PARTICIPANT){std::cout << "New participant discovered" << std::endl; // 输出“发现新域参与者”日志// 可根据发现信息中的字段修改以下条件,判断是否忽略该域参与者bool ignoring_condition = false;if (ignoring_condition){should_be_ignored = true; // 请求忽略该新发现的域参与者}}// 处理“域参与者被移除”或“域参与者掉线”事件else if (status == eprosima::fastdds::rtps::ParticipantDiscoveryStatus::REMOVED_PARTICIPANT ||status == eprosima::fastdds::rtps::ParticipantDiscoveryStatus::DROPPED_PARTICIPANT){std::cout << "Participant lost" << std::endl; // 输出“域参与者丢失”日志}}#if HAVE_SECURITY // 仅在启用安全功能时编译此部分代码// 域参与者身份认证回调void onParticipantAuthentication(DomainParticipant* participant,eprosima::fastdds::rtps::ParticipantAuthenticationInfo&& info) override{// 处理“域参与者认证通过”事件if (info.status == eprosima::fastdds::rtps::ParticipantAuthenticationInfo::AUTHORIZED_PARTICIPANT){std::cout << "A participant was authorized" << std::endl; // 输出“域参与者认证通过”日志}// 处理“域参与者认证失败”事件else if (info.status == eprosima::fastdds::rtps::ParticipantAuthenticationInfo::UNAUTHORIZED_PARTICIPANT){std::cout << "A participant failed authorization" << std::endl; // 输出“域参与者认证失败”日志}}#endif // 结束HAVE_SECURITY条件编译块// 数据读取器发现回调void on_data_reader_discovery(DomainParticipant* participant,eprosima::fastdds::rtps::ReaderDiscoveryStatus reason,const eprosima::fastdds::rtps::SubscriptionBuiltinTopicData& info,bool& should_be_ignored) override{should_be_ignored = false; // 默认不忽略新发现的数据读取器// 处理“发现新数据读取器”事件if (reason == eprosima::fastdds::rtps::ReaderDiscoveryStatus::DISCOVERED_READER){std::cout << "New datareader discovered" << std::endl; // 输出“发现新数据读取器”日志// 可根据发现信息中的字段修改以下条件,判断是否忽略该数据读取器bool ignoring_condition = false;if (ignoring_condition){should_be_ignored = true; // 请求忽略该新发现的数据读取器}}// 处理“数据读取器被移除”事件else if (reason == eprosima::fastdds::rtps::ReaderDiscoveryStatus::REMOVED_READER){std::cout << "Datareader lost" << std::endl; // 输出“数据读取器丢失”日志}}// 数据写入器发现回调void on_data_writer_discovery(DomainParticipant* participant,eprosima::fastdds::rtps::WriterDiscoveryStatus reason,const eprosima::fastdds::dds::PublicationBuiltinTopicData& info,bool& should_be_ignored) override{// 强制转换以避免“未使用参数”的编译警告static_cast<void>(participant);static_cast<void>(info);should_be_ignored = false; // 默认不忽略新发现的数据写入器// 处理“发现新数据写入器”事件if (reason == eprosima::fastdds::rtps::WriterDiscoveryStatus::DISCOVERED_WRITER){std::cout << "New datawriter discovered" << std::endl; // 输出“发现新数据写入器”日志// 可根据发现信息中的字段修改以下条件,判断是否忽略该数据写入器bool ignoring_condition = false;if (ignoring_condition){should_be_ignored = true; // 请求忽略该新发现的数据写入器}}// 处理“数据写入器被移除”事件else if (reason == eprosima::fastdds::rtps::WriterDiscoveryStatus::REMOVED_WRITER){std::cout << "Datawriter lost" << std::endl; // 输出“数据写入器丢失”日志}}};
代码说明
- 构造与析构函数:自定义监听器类
CustomDomainParticipantListener
继承自DomainParticipantListener
,构造函数调用父类构造函数,析构函数为虚函数(确保子类对象销毁时正确调用父类析构逻辑)。 - 事件处理逻辑:每个回调函数均通过判断事件状态(如
DISCOVERED_PARTICIPANT
、REMOVED_READER
)区分事件类型,并输出对应日志;同时提供ignoring_condition
变量,支持根据业务需求自定义“是否忽略实体”的判断逻辑。 - 安全功能适配:
onParticipantAuthentication()
回调被包裹在#if HAVE_SECURITY
条件编译块中,仅在启用安全功能时生效,符合 Fast DDS 的安全机制设计。