OpenDDS中避免订阅发布同一主题时的自环现象(适用于所有DDS)

本文介绍了在OpenDDS中如何通过DataReaderListener进行消息过滤,使用Partition进行数据隔离以及利用不同的Topic来防止自环现象,以提升系统稳定性和可靠性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、摘要

在 OpenDDS 中,同时订阅并发布同一主题会导致自环现象,即接收到自己发送的消息。本文介绍了在 OpenDDS 中避免自环现象的解决方案,主要包括使用 DataReaderListener 进行过滤和使用 Partition 进行隔离的方法。通过这些方法,可以在应用层面有效地控制数据的接收,确保数据的正确处理,提高系统的稳定性和可靠性。

2、理解"自反传输"

在 OpenDDS 中,如果你订阅并且发布了同一个主题,会导致你收到自己发布的消息,这是正常的行为。这种情况通常称为 “自反传输” 或 “自环”,是 DDS 规范的一部分。

2、解决方案

2.1、使用 DataReaderListener 进行过滤

在 DataReaderListener 中可以实现对接收到的数据进行过滤,避免处理自己发送的消息。你可以在 on_data_available 回调中检查接收到的数据的源头,然后决定是否处理。这样可以在应用层面进行控制。

示例代码:
在创建MyDataReaderListener 的时候将writerHandle传入进来。这里我的MyDataReaderListener 一个实例化对应一个主题。具体你还需要根据的场景进行修改。

class MyDataReaderListener : public virtual DDS::DataReaderListener {
public:
    MyDataReaderListener ( DDS::InstanceHandle_t writerHandle)
        ,m_dataWriterHandle{writerHandle}
    {}
    virtual void on_data_available(DDS::DataReader_ptr reader) {
        MyDataReader_var myReader = MyDataReader::_narrow(reader);
        if (!CORBA::is_nil(myReader.in())) {
            MyDataSeq dataSeq;
            DDS::SampleInfoSeq infoSeq;

            // 读取数据
            myReader->take(dataSeq, infoSeq, DDS::LENGTH_UNLIMITED, DDS::ANY_SAMPLE_STATE, DDS::ANY_VIEW_STATE, DDS::ANY_INSTANCE_STATE);

            for (DDS::ULong i = 0; i < dataSeq.length(); ++i) {
                // 检查数据源
                if (infoSeq[i].valid_data   && false == isFromLocalPublisher(info_seq[i])) {
                    // 处理数据
                }
            }
        }
    }
  virtual bool isFromLocalPublisher(const DDS::SampleInfo& info) {
        // 这里可以根据其他属性来判断是否是本地 Publisher 发布的数据
        // 比较dataWriter 的句柄等
        return (info.publication_handle != DDS::HANDLE_NIL && info.publication_handle == m_dataWriterHandle);
    }

private:
    DDS::InstanceHandle_t m_dataWriterHandle; // 本地 DataWriter 的实体ID
};

// writerHandle 的获取方式
writerHandle = dataWriter->get_instance_handle();

3.2、使用 Partition 进行隔离

在 OpenDDS 中,可以使用 Partition 来实现数据的隔离,使得一组 DataReader 和 DataWriter 只能收到和发送特定 Partition 的数据。你可以为你的 DataReader 和 DataWriter 指定不同的 Partition,这样就能确保一个 DataReader 不会接收到自己发送的消息。

示例代码:

DDS::DataReaderQos readerQos;
DDS::PublisherQos publisherQos;

// 设置 DataReader 和 DataWriter 的 Partition
readerQos.partition.name.length(1);
readerQos.partition.name[0] = "MyPartition1";

publisherQos.partition.name.length(1);
publisherQos.partition.name[0] = "MyPartition2";

3.3、 使用不同的 Topic

如果你的应用场景允许,可以考虑使用不同的 Topic 来区分你发布和订阅的数据。这样即使你同时订阅和发布相同的 Topic,由于数据的内容属性不同,也可以区分出自己发送的消息和其他人发送的消息。

总结

以上是一些常见的方法,你可以根据你的实际需求和应用场景选择合适的方法来避免接收到自己发送的消息。无论选择哪种方法,都需要根据你的需求进行合适的配置和处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林夕07

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值