【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 的安全机制设计。
相关推荐
韩曙亮6 分钟前
【自动驾驶】自动驾驶概述 ⑤ ( 自动驾驶硬件概述 | 车载计算单元 IPC | 车辆线控系统 )
自动驾驶·ipc·无人驾驶·域控制器·线控系统·车载计算单元
Zfox_3 小时前
【C++项目】微服务即时通讯系统:服务端
数据库·c++·微服务·中间件·rpc·架构·即时通讯
铮铭3 小时前
【论文阅读】OpenDriveVLA:基于大型视觉语言动作模型的端到端自动驾驶
人工智能·机器学习·自动驾驶
一碗白开水一5 小时前
【第30话:路径规划】自动驾驶中Hybrid A星(A*)搜索算法的详细推导及代码示例
人工智能·算法·机器学习·计算机视觉·数学建模·自动驾驶
ShowMaker.wins7 小时前
目标检测进化史
人工智能·python·神经网络·目标检测·计算机视觉·自动驾驶·视觉检测
铮铭19 小时前
【论文阅读】AutoDrive-R^2: 激励自动驾驶VLA模型的推理与自我反思能力
论文阅读·人工智能·自动驾驶
一條狗1 天前
学习日报 20250921|MQ (Kafka)面试深度复盘
java·中间件·kafka
你的微笑,乱了夏天1 天前
spring boot项目使用Torna生成在线接口文档
java·spring boot·中间件·postman
承悦赋1 天前
初识Redis:解锁高性能缓存的魔法钥匙
数据库·spring boot·redis·分布式·缓存·中间件
-点点-9 天前
电磁兼容性(EMC)法规
自动驾驶