【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 的安全机制设计。
相关推荐
Hi2024021710 小时前
使用 darkSCNN 和 Caffe 进行车道线检测
人工智能·深度学习·opencv·自动驾驶·caffe·车道线检测
Ray Song21 小时前
【FastDDS】Layer DDS之Domain (01-overview)
中间件·自动驾驶·fastdds·dds层概览
Thuni_soft1 天前
权威认证!华宇TAS应用中间件获得商用密码产品认证证书
中间件·商用密码认证
慧都小项1 天前
构建安全的自动驾驶:软件测试中的编码规范与AI验证
人工智能·测试工具·安全·自动驾驶·parasoft
ByteBlossom2 天前
SpringBoot集成Kafka实战应用
spring boot·中间件·kafka
一碗白开水一2 天前
【论文阅读】Sparse4D v3:Advancing End-to-End 3D Detection and Tracking
论文阅读·人工智能·目标检测·3d·自动驾驶
驾驭人生2 天前
基本IP保护 Swagger UI 的中间件
中间件
瀚高PG实验室2 天前
金蝶中间件适配HGDB
中间件·瀚高数据库
武子康2 天前
Java-114 深入浅出 MySQL 开源分布式中间件 ShardingSphere 深度解读
java·数据库·分布式·mysql·中间件·性能优化·开源