【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 的完整代码示例,实现了上述所有非标准回调函数,展示了如何处理域参与者、数据读取器、数据写入器的发现事件及身份认证事件:

cpp 复制代码
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; // 输出"数据写入器丢失"日志
        }
    }

};

代码说明

  1. 构造与析构函数 :自定义监听器类 CustomDomainParticipantListener 继承自 DomainParticipantListener,构造函数调用父类构造函数,析构函数为虚函数(确保子类对象销毁时正确调用父类析构逻辑)。
  2. 事件处理逻辑 :每个回调函数均通过判断事件状态(如 DISCOVERED_PARTICIPANTREMOVED_READER)区分事件类型,并输出对应日志;同时提供 ignoring_condition 变量,支持根据业务需求自定义"是否忽略实体"的判断逻辑。
  3. 安全功能适配onParticipantAuthentication() 回调被包裹在 #if HAVE_SECURITY 条件编译块中,仅在启用安全功能时生效,符合 Fast DDS 的安全机制设计。
相关推荐
LVXIANGAN2 天前
汽车智能座舱中LVDS、CAN、以太网、RTP的区别
自动驾驶·汽车
SunnyRivers2 天前
LangChain中间件详解
中间件·langchain
金刚猿2 天前
06_虚拟机中间件部署_xxl-job 部署
中间件·xxl-job·xxl-job-admin
地平线开发者3 天前
【地平线 征程 6 工具链进阶教程】算子优化方案集锦
算法·自动驾驶
无忧智库3 天前
某港口集团“十五五”智慧港口数字孪生与自动驾驶集卡多车编队系统建设方案深度解析(WORD)
人工智能·机器学习·自动驾驶
Loo国昌3 天前
【AI应用开发实战】Guardrail风险控制中间件:Agent系统的安全防线
人工智能·python·安全·自然语言处理·中间件·prompt
田里的水稻4 天前
OE_ubuntu24.04安装ros2
人工智能·算法·数学建模·机器人·自动驾驶
键盘鼓手苏苏4 天前
Flutter for OpenHarmony: Flutter 三方库 ntp 精准同步鸿蒙设备系统时间(分布式协同授时利器)
android·分布式·算法·flutter·华为·中间件·harmonyos
宝贝儿好4 天前
【强化学习】第十章:随机高斯策略
人工智能·python·深度学习·神经网络·机器人·自动驾驶
Coder_Boy_4 天前
Java后端核心技术体系全解析(个人总结)
java·开发语言·spring boot·分布式·spring cloud·中间件