目錄
- 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,由于數據的內容或屬性不同,也可以區分出自己發送的消息和其他人發送的消息。
總結
以上是一些常見的方法,你可以根據你的實際需求和應用場景選擇合適的方法來避免接收到自己發送的消息。無論選擇哪種方法,都需要根據你的需求進行合適的配置和處理。