DDS通信中間件——DCPS規(guī)范(上)
本篇文章繼續(xù)和大家分享一下對(duì)DDS這套規(guī)范的理解。預(yù)期本系列文章將包括以下內(nèi)容陸續(xù)更新:
1. DDS規(guī)范概述
2.DCPS規(guī)范解讀
3. DDS-XTypes與IDL解讀
4. RTPS規(guī)范解讀
5. DDS安全規(guī)范解讀
6. DDS-RPC規(guī)范解讀
7. DDS-TSN規(guī)范解讀
8. DDS-XRCE規(guī)范解讀
DCPS規(guī)范分為上下兩篇,本篇內(nèi)容先講模型概述、接口定義和開(kāi)發(fā)示例,下篇再來(lái)講QoS定義。
1. 概述
DCPS(Data-CentricPublish-Subscribe,以數(shù)據(jù)為中心的發(fā)布/訂閱)規(guī)范是DDS系列規(guī)范最初也是最核心的規(guī)范,在某些場(chǎng)合DDS規(guī)范指的就是DCPS規(guī)范。
2. DCPS-PIM
DCPS的內(nèi)容總結(jié)在下面這張圖中,主要分為三大塊,這篇文章也將按照導(dǎo)圖中的內(nèi)容依次介紹:
- ? 模型描述,介紹模型中涉及的概念;
- ? 接口描述,分模塊定義類(lèi)并定義接口形式及接口功能描述;
- ? QoS定義,定義22種QoS的功能及其配置方式。
2.1. 模型描述
2.1.1. 實(shí)體概念
- 基于主題的發(fā)布/訂閱模型
- 系統(tǒng)的數(shù)據(jù)按照主題來(lái)分類(lèi);
- 發(fā)布端發(fā)布主題數(shù)據(jù);
- 訂閱端訂閱主題數(shù)據(jù);
- 發(fā)布端發(fā)布的主題數(shù)據(jù)后,相同主題的訂閱端都能收到。
- DCPS實(shí)體模型定義了三層實(shí)體,如下圖所示
- 域參與者(DomainParticipant)
- 這個(gè)實(shí)體看上去和發(fā)布/訂閱模型沒(méi)啥關(guān)系,實(shí)際上也沒(méi)啥關(guān)系。主要是DDS里面定義域的概念用來(lái)隔離通信,相同域內(nèi)實(shí)體互相通信,不同域間隔離;
- 這是應(yīng)用參加DDS系統(tǒng)通信的入口實(shí)體,創(chuàng)建某個(gè)域下的域參與者表示:“我想要參與某個(gè)域進(jìn)行通信(是發(fā)布還是訂閱后面再告訴你)”。
- 發(fā)布者(Publisher)
- 這個(gè)最好理解,應(yīng)用創(chuàng)建發(fā)布者表示:“我需要發(fā)布數(shù)據(jù)(具體發(fā)布什么主題數(shù)據(jù),后面再告訴你)”;
- 訂閱者(Subscriber)
- 這個(gè)也很好理解,應(yīng)用創(chuàng)建訂閱者表示:“我需要訂閱數(shù)據(jù)(具體訂閱什么主題數(shù)據(jù),后面再告訴你)”;
- 主題(Topic)
- 主題用來(lái)描述一類(lèi)數(shù)據(jù),創(chuàng)建主題表示:“我有這么一類(lèi)數(shù)據(jù)需要交互”;
- 定義主題需要什么信息,后面章節(jié)詳細(xì)介紹;
- 數(shù)據(jù)寫(xiě)者(DataWriter)
- 數(shù)據(jù)寫(xiě)者關(guān)聯(lián)一個(gè)且僅一個(gè)主題實(shí)體,用來(lái)向全局?jǐn)?shù)據(jù)空間寫(xiě)指定主題的數(shù)據(jù);
- 應(yīng)用創(chuàng)建數(shù)據(jù)寫(xiě)者表示:“我需要發(fā)布XX主題數(shù)據(jù)?!?/li>
- 數(shù)據(jù)讀者(DataReader)
- 數(shù)據(jù)讀者關(guān)聯(lián)一個(gè)且僅一個(gè)主題實(shí)體,用來(lái)從全局?jǐn)?shù)據(jù)空間讀指定主題的數(shù)據(jù);
- 應(yīng)用創(chuàng)建數(shù)據(jù)讀者表示:“我需要訂閱XX主題數(shù)據(jù)。”
2.1.2. 數(shù)據(jù)描述
DCPS模型中有幾個(gè)重要的概念來(lái)描述系統(tǒng)中傳輸?shù)臄?shù)據(jù),如下圖所示自頂向下分為三層來(lái)描述系統(tǒng)中交互的數(shù)據(jù)。
概念 | 說(shuō)明 | 標(biāo)識(shí) |
---|---|---|
主題 | 最大類(lèi),域內(nèi)唯一的主題名稱(chēng),并關(guān)聯(lián)1個(gè)數(shù)據(jù)類(lèi)型。 | 主題名+類(lèi)型 |
實(shí)例 | 主題數(shù)據(jù)中key成員相同的數(shù)據(jù)的集合,即使用key成員進(jìn)一步區(qū)分主題數(shù)據(jù),可以理解成“子主題”。 | InstanceHandle_t |
樣本 | 每次向DDS發(fā)送一次數(shù)據(jù)產(chǎn)生一個(gè)數(shù)據(jù)樣本。 | 序列號(hào) |
2.2. 接口描述
2.2.1. 基礎(chǔ)模塊
基礎(chǔ)模塊包含了DCPS的接口定義的幾個(gè)重要的原則:
實(shí)體管理(創(chuàng)建/刪除/查詢(xún))采用工廠模式,父實(shí)體為子實(shí)體的工廠,層級(jí)關(guān)系參見(jiàn)2.2.1節(jié);
每個(gè)實(shí)體會(huì)關(guān)聯(lián)一組內(nèi)部的狀態(tài);
狀態(tài)可以通過(guò)實(shí)體提供的查詢(xún)接口查詢(xún)獲??;
狀態(tài)可以通過(guò)監(jiān)聽(tīng)器由底層回調(diào)獲?。?/p>
狀態(tài)可以通過(guò)“條件-等待”的方式同步阻塞獲??;
每個(gè)實(shí)體都會(huì)關(guān)聯(lián)一系列的QoS配置。
2.2.1.1. 實(shí)體狀態(tài)
實(shí)體狀態(tài)表示DDS為用戶關(guān)心的底層事件所維護(hù)的狀態(tài),例如數(shù)據(jù)寫(xiě)者關(guān)聯(lián)成功匹配遠(yuǎn)程數(shù)據(jù)讀者、檢測(cè)到數(shù)據(jù)讀者數(shù)據(jù)樣本丟失、檢測(cè)到主題的類(lèi)型不兼容等。每個(gè)實(shí)體會(huì)關(guān)聯(lián)一系列的代表該實(shí)體“通信狀態(tài)”的狀態(tài)對(duì)象。實(shí)體關(guān)聯(lián)的狀態(tài)參見(jiàn)下圖。狀態(tài)結(jié)構(gòu)體中包含的數(shù)值可以提供更多關(guān)于該狀態(tài)的信息。
2.2.1.2. 獲取實(shí)體狀態(tài)
狀態(tài)分為兩種類(lèi)型:
- 簡(jiǎn)單通信狀態(tài) :除了表明狀態(tài)是否改變的標(biāo)識(shí)還包含保存當(dāng)前狀態(tài)的對(duì)應(yīng)結(jié)構(gòu)體。
- 讀通信狀態(tài):讀通信狀態(tài)更像一個(gè)事件,除了是否發(fā)生以外沒(méi)有其他聲明。只有兩個(gè)狀態(tài)是讀通信狀態(tài):#DATA_AVAILABLE_STATUS 和 #DATA_ON_READERS_STATUS 。
下面分別描述獲取實(shí)體簡(jiǎn)單通信狀態(tài)有三種方式 :
- 同步獲取實(shí)體狀態(tài),參見(jiàn)上圖最左邊圖,用戶想要獲取某個(gè)狀態(tài)的當(dāng)前值時(shí),主動(dòng)調(diào)用該狀態(tài)有關(guān)的實(shí)體方法,獲取各實(shí)體狀態(tài)的實(shí)體方法參見(jiàn)2.2.1.1中的圖;
- 同步等待并獲取實(shí)體狀態(tài),參見(jiàn)上圖中間的圖,用戶設(shè)置等待條件,并調(diào)用DDS接口進(jìn)行阻塞等待,在DDS底層檢測(cè)到該狀態(tài)發(fā)生變化后,解開(kāi)阻塞,用戶再通過(guò)方法1獲取該狀態(tài);
- 異步回調(diào)實(shí)體狀態(tài),參見(jiàn)上圖右邊的圖,該方式為通過(guò)監(jiān)聽(tīng)器異步回調(diào)狀態(tài) ,用戶為實(shí)體設(shè)置相應(yīng)的監(jiān)聽(tīng)器(再進(jìn)行其他的業(yè)務(wù)邏輯),DDS底層檢測(cè)到該狀態(tài)變化時(shí),通過(guò)回調(diào)監(jiān)聽(tīng)器的相應(yīng)方法,用戶即可獲取該狀態(tài)的值,各實(shí)體狀態(tài)關(guān)聯(lián)的回調(diào)方法參見(jiàn)參見(jiàn)2.2.1.1中的圖。
2.2.1.3. 條件-等待
DDS使用條件( Condition )以及等待( WaitSet )來(lái)實(shí)現(xiàn)同步等待模型,其中每個(gè)條件均有一個(gè)觸發(fā)狀態(tài),不同類(lèi)型的狀態(tài)的觸發(fā)條件不一樣,可以將一個(gè)或者多個(gè)條件加入到等待集合中,即允許用戶同時(shí)等待多個(gè)狀態(tài)的集合中的某個(gè)狀態(tài)觸發(fā)。條件的類(lèi)型及其相關(guān)的操作參見(jiàn),使用條件等待的詳細(xì)例子參見(jiàn):
說(shuō)明 | 狀態(tài)條件( StatusCondition ) | 讀取條件 ( ReadCondition ) | 監(jiān)視條件( GuardCondition ) |
---|---|---|---|
簡(jiǎn)介 | 該條件用于獲取實(shí)體狀態(tài)改變 | 該條件用于獲取數(shù)據(jù)讀者的數(shù)據(jù)狀態(tài)改變 | 該條件用于手動(dòng)解開(kāi)阻塞的條件集合 |
獲取方式 | 每個(gè)實(shí)體均會(huì)關(guān)聯(lián)一個(gè)該條件,調(diào)用 Entity::get_statuscondition 方法獲取 | 由數(shù)據(jù)讀者作為該條件的工廠, DataReader::create_readcondition 、 DataReader::delete_readcondition | 用戶負(fù)責(zé)狀態(tài)的生命周期管理 (new/delete) |
觸發(fā)方式 | StatusCondition::set_enabled_statuses 設(shè)置的關(guān)心的狀態(tài)發(fā)生改變 | 數(shù)據(jù)讀者底層有該狀態(tài)所表示的數(shù)據(jù)樣本的時(shí)候觸發(fā) | 用戶通過(guò)監(jiān)視條件的接口手動(dòng)設(shè)置 |
觸發(fā)后的動(dòng)作 | 首先測(cè)試發(fā)生改變的狀態(tài),再調(diào)用相應(yīng)的狀態(tài)獲取方法獲取 | 調(diào)用數(shù)據(jù)讀者的讀取數(shù)據(jù)方法獲取改變的數(shù)據(jù) DataReader::read_w_condition DataReader::take_w_condition | 無(wú) |
(向左滑動(dòng))
2.2.1.4. 監(jiān)聽(tīng)器
DDS通過(guò)監(jiān)聽(tīng)器提供底層狀態(tài)事件異步回調(diào)的機(jī)制,每個(gè)實(shí)體狀態(tài)在相應(yīng)的實(shí)體監(jiān)聽(tīng)器中均有相應(yīng)的回調(diào)函數(shù)與之對(duì)應(yīng),實(shí)體回調(diào)函數(shù)與實(shí)體狀態(tài)的對(duì)應(yīng)關(guān)系參見(jiàn) 2.2.1.1中的圖 。下圖顯示了DDS中各個(gè)監(jiān)聽(tīng)器的繼承關(guān)系,即父實(shí)體的監(jiān)聽(tīng)器繼承于子類(lèi)的監(jiān)聽(tīng)器,這就意味著父實(shí)體監(jiān)聽(tīng)器能夠獲取所有子實(shí)體的狀態(tài)變化。
2.2.2. 域模塊
在發(fā)布訂閱模型中,理論上每個(gè)計(jì)算機(jī)上的中間件都需要掌握全局的節(jié)點(diǎn)信息,以提供分布式的數(shù)據(jù)傳輸服務(wù)。但在實(shí)際應(yīng)用中,可能存在需要隔離的情況,例如網(wǎng)絡(luò)中的節(jié)點(diǎn)數(shù)量過(guò)于龐大,掌握全局信息會(huì)付出巨大的代價(jià),或者從屬于不同分區(qū)的小組之間不希望互相干擾。為了解決隔離的問(wèn)題,DDS引入了域的概念。每個(gè)參與通信的計(jì)算機(jī)都可以加入一個(gè)或多個(gè)域,相同域內(nèi)的節(jié)點(diǎn)可以互相通信,不同域之間的節(jié)點(diǎn)則不會(huì)有數(shù)據(jù)交互。DDS中使用 DomainId_t 來(lái)唯一標(biāo)識(shí)一個(gè)域。域參與者實(shí)體是DDS的入口,用戶創(chuàng)建一個(gè)域參與者表示該程序想要在指定的域中交互數(shù)據(jù)。域模型示意圖參見(jiàn)下圖,一個(gè)應(yīng)用程序可以在多個(gè)域中交互數(shù)據(jù)。
2.2.2.1. 域參與者工廠
域參與者實(shí)體的工廠為全局單例的域參與者工廠( DomainParticipantFactory ),域參與者工廠的主要功能參見(jiàn)下表。
功能 | 接口 |
---|---|
單例管理 | DomainParticipantFactory::get_instance |
DomainParticipantFactory::finalize_instance | |
作為域參與者的工廠 | DomainParticipantFactory::create_participant |
DomainParticipantFactory::delete_participant | |
DomainParticipantFactory::lookup_participant | |
DomainParticipantFactory::get_default_participant_qos | |
DomainParticipantFactory::set_default_participant_qos | |
自身QoS管理 | DomainParticipantFactory::set_qos |
DomainParticipantFactory::get_qos |
(向左滑動(dòng))
2.2.2.2. 域參與者
域參與者( DomainParticipant ),主要接口的功能參見(jiàn)下表,此外,域參與者內(nèi)部還實(shí)現(xiàn)發(fā)現(xiàn)協(xié)議、根據(jù)線程模型配置初始化線程、創(chuàng)建定時(shí)器、申請(qǐng)并創(chuàng)建網(wǎng)絡(luò)傳輸需要的資源,并監(jiān)聽(tīng)對(duì)應(yīng)的網(wǎng)絡(luò)端口,負(fù)責(zé)處理網(wǎng)絡(luò)報(bào)文等,域參與者所需的資源較多,內(nèi)部邏輯復(fù)雜,因而在一個(gè)應(yīng)用中應(yīng)盡可能的減少域參與者的創(chuàng)建。
功能 | 接口 |
---|---|
實(shí)體功能 | DomainParticipant::enable |
DomainParticipant::set_listener | |
DomainParticipant::get_listener | |
DomainParticipant::set_qos | |
DomainParticipant::get_qos | |
DomainParticipant::get_instance_handle | |
DomainParticipant::get_status_changes | |
DomainParticipant::get_statuscondition | |
作為實(shí)體工廠 | DomainParticipant::delete_contained_entities |
DomainParticipant::contains_entity | |
作為主題實(shí)體工廠 | DomainParticipant::create_topic |
DomainParticipant::delete_topic | |
DomainParticipant::get_default_topic_qos | |
DomainParticipant::set_default_topic_qos | |
DomainParticipant::lookup_topicdescription | |
DomainParticipant::find_topic | |
DomainParticipant::create_contentfilteredtopic | |
DomainParticipant::delete_contentfilteredtopic | |
作為發(fā)布者實(shí)體工廠 | DomainParticipant::create_publisher |
DomainParticipant::delete_publisher | |
DomainParticipant::get_default_publisher_qos | |
DomainParticipant::set_default_publisher_qos | |
DomainParticipant::get_publishers | |
作為訂閱者實(shí)體工廠 | DomainParticipant::create_subscriber |
DomainParticipant::delete_subscriber | |
DomainParticipant::get_default_subscriber_qos | |
DomainParticipant::set_default_subscriber_qos | |
DomainParticipant::get_subscribers | |
內(nèi)置實(shí)體管理 | DomainParticipant::get_builtin_subscriber |
通信管理 | DomainParticipant::ignore_participant |
DomainParticipant::ignore_publication | |
DomainParticipant::ignore_subscription | |
域信息查詢(xún) | DomainParticipant::get_domain_id |
DomainParticipant::get_discovered_participants | |
DomainParticipant::get_discovered_participant_data | |
DomainParticipant::get_discovered_topics | |
DomainParticipant::get_discovered_topic_data | |
存活性管理 | DomainParticipant::assert_liveliness |
2.2.3. 主題模塊
功能 | 接口 |
---|---|
實(shí)體功能 | Topic::enable |
Topic::set_listener | |
Topic::get_listener | |
Topic::get_instance_handle | |
Topic::get_status_changes | |
Topic::get_statuscondition | |
Topic::set_qos | |
Topic::get_qos | |
獲取主題信息 | Topic::get_type_name |
Topic::get_name |
2.2.4. 發(fā)布模塊
2.2.4.1. 發(fā)布者
功能 | 接口 |
---|---|
實(shí)體功能 | Publisher::enable |
Publisher::set_listener | |
Publisher::get_listener | |
Publisher::get_instance_handle | |
Publisher::get_status_changes | |
Publisher::get_statuscondition | |
Publisher::get_participant | |
Publisher::set_qos | |
Publisher::get_qos | |
作為數(shù)據(jù)寫(xiě)者的工廠 | Publisher::create_datawriter |
Publisher::delete_datawriter | |
Publisher::lookup_datawriter | |
Publisher::delete_contained_entities | |
Publisher::set_default_datawriter_qos | |
Publisher::get_default_datawriter_qos | |
Publisher::copy_from_topic_qos | |
數(shù)據(jù)發(fā)布控制 | Publisher::begin_coherent_changes |
Publisher::end_coherent_changes | |
Publisher::wait_for_acknowledgments | |
Publisher::suspend_publications | |
Publisher::resume_publications |
2.2.4.2. 數(shù)據(jù)寫(xiě)者
數(shù)據(jù)寫(xiě)者主要的功能描述參見(jiàn)下表,數(shù)據(jù)寫(xiě)者提供強(qiáng)類(lèi)型安全的接口,該接口由DDS編譯器根據(jù)IDL中定義的類(lèi)型自動(dòng)生成,其中類(lèi)型無(wú)關(guān)的接口參見(jiàn) DataWriter 、類(lèi)型相關(guān)的接口參見(jiàn) ExampleDataWriter 接口說(shuō)明,典型的發(fā)布過(guò)程如下 。
功能 | 接口 |
---|---|
實(shí)體功能 | DataWriter::enable |
DataWriter::set_listener | |
DataWriter::get_listener | |
DataWriter::get_instance_handle | |
DataWriter::get_status_changes | |
DataWriter::get_statuscondition | |
DataWriter::set_qos | |
DataWriter::get_qos | |
數(shù)據(jù)發(fā)送 | ExampleDataWriter::write |
ExampleDataWriter::write_w_timestamp | |
ExampleDataWriter::write_w_dst | |
數(shù)據(jù)實(shí)例管理 | ExampleDataWriter::register_instance |
ExampleDataWriter::register_instance_w_timestamp | |
ExampleDataWriter::unregister_instance | |
ExampleDataWriter::unregister_instance_w_timestamp | |
ExampleDataWriter::dispose | |
ExampleDataWriter::dispose_w_timestamp | |
ExampleDataWriter::get_key_value | |
ExampleDataWriter::lookup_instance | |
實(shí)體狀態(tài)查詢(xún) | DataWriter::get_liveliness_lost_status |
DataWriter::get_offered_deadline_missed_status | |
DataWriter::get_offered_incompatible_qos_status | |
DataWriter::get_publication_matched_status | |
數(shù)據(jù)寫(xiě)者信息查詢(xún) | DataWriter::get_topic |
DataWriter::get_publisher | |
匹配對(duì)端信息查詢(xún) | DataWriter::get_matched_subscriptions |
DataWriter::get_matched_subscription_data | |
存活性管理 | DataWriter::assert_liveliness |
其他 | DataWriter::wait_for_acknowledgments |
DataWriter::flush |
(向左滑動(dòng))
2.2.5. 訂閱模塊
2.2.5.1. 訂閱者
功能 | 接口 |
---|---|
實(shí)體功能 | Subscriber::enable |
Subscriber::set_listener | |
Subscriber::get_listener | |
Subscriber::get_instance_handle | |
Subscriber::get_status_changes | |
Subscriber::get_statuscondition | |
Subscriber::get_participant | |
Subscriber::set_qos | |
Subscriber::get_qos | |
作為數(shù)據(jù)讀者的工廠 | Subscriber::create_datareader |
Subscriber::delete_datareader | |
Subscriber::lookup_datareader | |
Subscriber::delete_contained_entities | |
Subscriber::set_default_datareader_qos | |
Subscriber::get_default_datareader_qos | |
Subscriber::copy_from_topic_qos | |
數(shù)據(jù)獲取方式 | Subscriber::begin_access |
Subscriber::end_access | |
Subscriber::get_datareaders | |
Subscriber::notify_datareaders |
(向左滑動(dòng))
2.2.5.2. 數(shù)據(jù)讀者
數(shù)據(jù)讀者的類(lèi)型無(wú)關(guān)功能描述參見(jiàn)下表,數(shù)據(jù)讀者提供強(qiáng)類(lèi)型安全的接口,該接口由DDS編譯器根據(jù)IDL中定義的類(lèi)型自動(dòng)生成,其中類(lèi)型無(wú)關(guān)的接口參見(jiàn)DataReader 、類(lèi)型相關(guān)的接口參見(jiàn) ExampleDataReader 接口說(shuō)明。
功能 | 接口 |
---|---|
實(shí)體功能 | DataReader::enable |
DataReader::set_listener | |
DataReader::get_listener | |
DataReader::get_instance_handle | |
DataReader::get_status_changes | |
DataReader::get_statuscondition | |
DataReader::set_qos | |
DataReader::get_qos | |
實(shí)體狀態(tài)查詢(xún) | DataReader::get_sample_lost_status |
DataReader::get_sample_rejected_status | |
DataReader::get_subscription_matched_status | |
DataReader::get_liveliness_changed_status | |
DataReader::get_requested_deadline_missed_status | |
DataReader::get_requested_incompatible_qos_status | |
數(shù)據(jù)讀者信息查詢(xún) | DataReader::get_topicdescription |
DataReader::get_subscriber | |
匹配對(duì)端信息查詢(xún) | DataReader::get_matched_publications |
DataReader::get_matched_publication_data | |
讀取狀態(tài)管理 | DataReader::create_readcondition |
DataReader::create_querycondition | |
DataReader::delete_readcondition | |
DataReader::delete_contained_entities | |
其他 | DataReader::wait_for_historical_data |
(向左滑動(dòng))
2.2.5.3. 獲取主題數(shù)據(jù)
當(dāng)數(shù)據(jù)樣本到達(dá)訂閱端時(shí),DDS底層會(huì)根據(jù)主題匹配信息分發(fā)給不同的數(shù)據(jù)讀者去處理,當(dāng)完成處理(資源限制等QoS配置)時(shí),數(shù)據(jù)讀者將把該數(shù)據(jù)樣本存儲(chǔ)在底層的隊(duì)列中,并通知用戶,再等待用戶通過(guò)接口來(lái)取出該數(shù)據(jù)樣本,DDS通知用戶數(shù)據(jù)到達(dá)的方式有兩種:異步監(jiān)聽(tīng)方式以及同步等待方式,用戶通過(guò)數(shù)據(jù)讀者的讀取數(shù)據(jù)接口訪問(wèn)底層隊(duì)列中的數(shù)據(jù)樣本,這些接口的摘要信息參見(jiàn)下表,詳細(xì)信息參見(jiàn)相應(yīng)的接口說(shuō)明。用戶可以通過(guò)多種方式訪問(wèn)底層存儲(chǔ)的隊(duì)列數(shù)據(jù):
1. 提供樣本深拷貝以及零拷貝(僅提供數(shù)據(jù)樣本在底層隊(duì)列中的指針或者引用)兩種方式;
2. 指定最大獲取數(shù)量;
3. 訪問(wèn)處于指定狀態(tài)的樣本,樣本狀態(tài)由 SampleStateKind 、 ViewStateKind 、 InstanceStateKind 三個(gè)狀態(tài)定義;
4. 按照數(shù)據(jù)實(shí)例訪問(wèn),包括指定數(shù)據(jù)實(shí)例以及按數(shù)據(jù)實(shí)例順序;
5. 按照樣本的順序依次訪問(wèn);
6. 讀取/取出兩種訪問(wèn)方法,其中讀取操作不從底層隊(duì)列中刪除,而取出操作則從底層維護(hù)的樣本中刪除。
分類(lèi) | 接口 | 說(shuō)明 |
---|---|---|
讀取系列 | ExampleDataReader::read | 方式1 & 方式2 & 方式3 |
ExampleDataReader::read_next_sample | 方式5 | |
ExampleDataReader::read_instance | 方式1 & 方式2 & 方式3 & 方式4 | |
ExampleDataReader::read_next_instance | 方式1 & 方式2 & 方式3 & 方式4 | |
ExampleDataReader::read_w_condition | 同 ExampleDataReader::read | |
ExampleDataReader::read_next_instance_w_condition | 同 ExampleDataReader::read_next_instance | |
取出系列 | ExampleDataReader::take | 方式1 & 方式2 & 方式3 |
ExampleDataReader::take_next_sample | 方式5 | |
ExampleDataReader::take_instance | 方式1 & 方式2 & 方式3 & 方式4 | |
ExampleDataReader::take_next_instance | 方式1 & 方式2 & 方式3 & 方式4 | |
ExampleDataReader::take_w_condition | 同 ExampleDataReader::take | |
ExampleDataReader::take_next_instance_w_condition | 同 ExampleDataReader::take_next_instance | |
歸還空間 | ExampleDataReader::return_loan | 配合實(shí)現(xiàn)零拷貝 |
(向左滑動(dòng))
2.3. QoS定義
下一期再繼續(xù)分享。
3. PSM-IDL
因?yàn)樯厦娑x的是平臺(tái)/技術(shù)無(wú)關(guān)的模型,在這一章OMG用IDL給出了DCPS的一種定義,所謂PIM就是只規(guī)定形式和行為,具體數(shù)據(jù)結(jié)構(gòu)在PSM中給出,這是OMG DDS規(guī)范的一般套路,打個(gè)比方,在PIM中會(huì)定義 InstanceHandle_t 這個(gè)結(jié)構(gòu)的含義是用來(lái)唯一標(biāo)識(shí)實(shí)體或者數(shù)據(jù)實(shí)例,但是不會(huì)規(guī)定如何來(lái)實(shí)現(xiàn),在PSM中會(huì)定義 InstanceHandle_t 就是8個(gè)字節(jié)或者16個(gè)字節(jié)。
4. 開(kāi)發(fā)流程
5. 代碼示例
5.1. 發(fā)布端
#include"DomainParticipantFactory.h"
#include"DomainParticipant.h"
#include"DefaultQos.h"
#include"Publisher.h"
#include"DataWriter.h"
#include"Topic.h"
#include"Foo.h"
#include"FooDataWriter.h"
#include"FooTypeSupport.h"
#include"ZRSleep.h"
#include
intmain()
{
//域
DomainId_tdomainId=11;
DomainParticipantFactory*factory=DomainParticipantFactory::get_instance();
//域參與者
DomainParticipant*participant=factory->create_participant(
domainId,
DOMAINPARTICIPANT_QOS_DEFAULT,
NULL,STATUS_MASK_NONE);
if(NULL==participant)
{
printf("createparticipantfailed.\n");
return-1;
}
//注冊(cè)類(lèi)型
constChar*type_name=FooTypeSupport::get_instance()->get_type_name();
if(type_name==NULL)
{
return-1;
}
ReturnCode_trtn=FooTypeSupport::get_instance()->register_type(participant,type_name);
if(rtn!=RETCODE_OK)
{
printf("registertypefailed.\n");
return-1;
}
//創(chuàng)建主題
Topic*topic=participant->create_topic("example",type_name,TOPIC_QOS_DEFAULT,NULL,STATUS_MASK_NONE);
if(topic==NULL)
{
printf("createtopicfailed.\n");
return-1;
}
//創(chuàng)建發(fā)布端
Publisher*publisher=participant->create_publisher(
PUBLISHER_QOS_DEFAULT,
NULL,STATUS_MASK_NONE);
if(publisher==NULL)
{
printf("createpublisherfailed.\n");
return-1;
}
//創(chuàng)建數(shù)據(jù)寫(xiě)者
DataWriterQoswriter_qos;
publisher->get_default_datawriter_qos(writer_qos);
writer_qos.history.depth=5;
DataWriter*writer=publisher->create_datawriter(
topic,writer_qos,NULL,STATUS_MASK_NONE);
FooDataWriter*_writer=dynamic_cast(writer);
if(writer==NULL)
{
printf("createdatawriterfailed.\n");
return-1;
}
//創(chuàng)建數(shù)據(jù)樣本
Foosample;
while(true)
{
//在此處修改數(shù)據(jù)樣本的值
//發(fā)布數(shù)據(jù)樣本
_writer->write(sample,HANDLE_NIL_NATIVE);
ZRSleep(1000);
}
return0;
}
(向左滑動(dòng))
5.2. 訂閱端
#include"DomainParticipantFactory.h"
#include"DomainParticipant.h"
#include"DefaultQos.h"
#include"Subscriber.h"
#include"DataReader.h"
#include"Topic.h"
#include"DataReaderListener.h"
#include"Foo.h"
#include"FooDataReader.h"
#include"FooTypeSupport.h"
#include"ZRSleep.h"
#include
//繼承DataReaderListener
classMylistener:publicDataReaderListener
{
//回調(diào)函數(shù)
voidon_data_available(DataReader*the_reader)
{
printf("receiveddata.\n");
FooDataReader*foo_reader=dynamic_cast(the_reader);
if(foo_reader==NULL)
{
printf("castreaderfailed.\n");
return;
}
FooSeqdata_values;
SampleInfoSeqsample_infos;
ReturnCode_trtn;
rtn=foo_reader->take(data_values,
sample_infos,
MAX_INT32_VALUE,
ANY_SAMPLE_STATE,
ANY_VIEW_STATE,
ANY_INSTANCE_STATE);
if(RETCODE_ERROR==rtn)
{
printf("takefailed.\n");
return;
}
if(RETCODE_NO_DATA==rtn)
{
printf("nodata.\n");
return;
}
for(inti=0;ilength();i++)
{
if(sample_infos[i].valid_data)
{
FooPrintData(&data_values[i]);
}
}
foo_reader->return_loan(data_values,sample_infos);
}
};
intmain()
{
//域
DomainId_tdomainId=11;
DomainParticipantFactory*factory=DomainParticipantFactory::get_instance();
//域參與者
DomainParticipant*participant=factory->create_participant(
domainId,
DOMAINPARTICIPANT_QOS_DEFAULT,
NULL,STATUS_MASK_NONE);
if(NULL==participant)
{
printf("createparticipantfailed.\n");
return-1;
}
//注冊(cè)類(lèi)型
constChar*type_name=FooTypeSupport::get_instance()->get_type_name();
if(NULL==type_name)
{
return-1;
}
ReturnCode_trtn=FooTypeSupport::get_instance()->register_type(participant,type_name);
if(RETCODE_OK!=rtn)
{
printf("registertypefailed.\n");
return-1;
}
//創(chuàng)建主題
Topic*topic=participant->create_topic("example",type_name,TOPIC_QOS_DEFAULT,NULL,STATUS_MASK_NONE);
if(NULL==topic)
{
printf("createtopicfailed.\n");
return-1;
}
//創(chuàng)建訂閱端
Subscriber*subscriber=participant->create_subscriber(
SUBSCRIBER_QOS_DEFAULT,
NULL,STATUS_MASK_NONE);
if(NULL==subscriber)
{
printf("createsubscriberfailed.\n");
return-1;
}
//監(jiān)聽(tīng)器
Mylistener*listener=newMylistener;
//創(chuàng)建數(shù)據(jù)讀者
DataReaderQosreader_qos;
subscriber->get_default_datareader_qos(reader_qos);
reader_qos.history.depth=5;
DataReader*reader=subscriber->create_datareader(
topic,reader_qos,listener,STATUS_MASK_ALL);
FooDataReader*_reader=dynamic_cast(reader);
if(NULL==reader)
{
printf("createdatareaderfailed.\n");
return-1;
}
while(true)
{
ZRSleep(1000);
}
return0;
}
(向左滑動(dòng))
-
通信
+關(guān)注
關(guān)注
18文章
6032瀏覽量
135993 -
中間件
+關(guān)注
關(guān)注
0文章
65瀏覽量
18176 -
DDS
+關(guān)注
關(guān)注
21文章
634瀏覽量
152663
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論