目录
- 1、摘要
- 2、理解"自反传输"
- 2、解决方案
- 2.1、使用 DataReaderListener 进行过滤
- 3.2、使用 Partition 进行隔离
- 3.3、 使用不同的 Topic
- 总结
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,由于数据的内容或属性不同,也可以区分出自己发送的消息和其他人发送的消息。
总结
以上是一些常见的方法,你可以根据你的实际需求和应用场景选择合适的方法来避免接收到自己发送的消息。无论选择哪种方法,都需要根据你的需求进行合适的配置和处理。