OPenDDS程序 的 实现+运行
標題DDS程序實現和運行
本文記錄了Windows10環境下OpenDDS環境搭建,idl自定義,代碼生成,代碼編寫的全過程。
一、環境搭建
1.詳細情況請參考開發筆記:1. OpenDDS環境搭建-Windows 10.note
編譯好后生成了兩個文件夾“OpenDDS-3.14”,“ACE_wrappers”這兩個文件夾就是本地的運行庫了。
2.部署兩臺計算機。
a)把上述的兩目錄文件拷貝過去,
b)確保兩臺電腦有同樣的開發環境.和設置同樣的環境變量.同樣的路徑.
設置環境變量
1)系統變量
ACE_ROOT F:\J18-ZaiJian\ACE_wrappers
MPC_ROOT F:\J18-ZaiJian\ACE_wrappers\MPC
TAO_ROOT %ACE_ROOT%\TAO
DDS_ROOT F:\J18-ZaiJian\OpenDDS-3.14
2)Path變量
在Path中添加:中添加:
%ACE_ROOT%\lib
%ACE_ROOT%\bin
%DDS_ROOT%\lib
%DDS_ROOT%\bin
二、生成相關代碼
0.新建工程目錄名稱:ZJ-DDS-220301
目錄地址:F:\J18-ZaiJian\ZJ-DDS-220301
1.右鍵點擊新建txt文件,名稱為Demo.idl。
編寫Demo.idl內容如下:
module DemoIdlModule {@topicstruct DemoTopic1 {@key long id;long counter;string text;}; };2.右鍵點擊新建txt文件,名稱為Demo.mpc文件,
將其與Demo.idl放置在一個文件夾,Demo.mpc文件內容如下:
project(*idl): dcps {TypeSupport_Files {Demo.idl}custom_only = 1 }project(*publisher) : dcpsexe_with_tcp {exename = publisherafter += *idlTypeSupport_Files {Demo.idl}Source_Files {Publisher.cpp} }project(*subscriber) : dcpsexe_with_tcp {exename = subscriberafter += *publisherTypeSupport_Files {Demo.idl}Source_Files {Subscriber.cppDataReaderListener.cpp} }3.右鍵點擊新建txt文件,名稱分別為:Publisher.cpp,Subscriber.cpp及DataReaderListener.h/DataReaderListener.cpp
4.使用vs開發人員命令行工具,輸入命令:
1)切到Demo.idl及Demo.mpc文件所在目錄;
cd F:\J18-ZaiJian\ZJ-DDS-220301 perl %ACE_ROOT%\MPC\mwc.pl -type vs2017//曾經我用的是這個命令,效果一樣:
perl %ACE_ROOT%\MPC\mwc.pl -type vs2017 -include %DDS_ROOT%\MPC\config2)代碼生成完畢后,文件如下圖:
3)雙擊ZJ_DDS_220301.sln,用vs2017打開如下:
5.右鍵單擊解決方案,選擇“重新生成解決方案”,查看是否能編譯通過。
vs解決方案以及文件夾生成的文件如下:
6.單獨為工程編寫一個配置文件config_Pub.ini和config_Sub.ini
用于對OpenDDS的協議,功能進行配置,config_Pub.ini和config_Sub.ini,如下:
[common] DCPSGlobalTransportConfig=$file DCPSDefaultDiscovery=DEFAULT_RTPS [transport/the_rtps_transport] transport_type=rtps_udp三、編寫代碼
● 發布端:從本地文件AAA.txt讀取數據,作為DDS主題數據,發布出去。
● 訂閱端:接收到主題數據后,將數據寫入本地文件BBB.txt中。
1. Publisher.cpp
#include <dds/DCPS/Service_Participant.h> #include <dds/DCPS/Marked_Default_Qos.h> #include <dds/DCPS/PublisherImpl.h> #include <dds/DCPS/transport/tcp/TcpInst.h> #include "dds/DCPS/StaticIncludes.h"#include <ace/streams.h>#include "DemoTypeSupportImpl.h" using namespace DemoIdlModule;int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) {try {// 初始化參與者argv[1] = "-DCPSConfigFile";argv[2] = "config_Pub.ini";argc = 3; #if 1 //0. 文件 //將參數從文件讀出,然后作為DDS傳輸的主題數據。FILE* fp;//char c[] = "The counter is: 5";char c[] = "2";char buffer[50] = { 0 };// char* buffer = { 0 };// int bufsize = 0;long _counter = 0; //用來交給6.公布數據的 message.counterchar fname[80] = "F:\\J18-ZaiJian\\AAA.txt";int charCount = 0;/** 保存文件的字符個數 **//* 打開文件用于讀 */if ((fp = fopen(fname, "r")) == NULL) {printf("Open file failed!!\n");exit(1);}while (fgetc(fp) != EOF) /** 統計字符個數 **/charCount++;/* 查找文件的開頭 */fseek(fp, 0, SEEK_SET);/* 讀取并顯示數據 */// fread(buffer, strlen(buffer) + 1, 1, fp);fread(buffer, charCount+1, 1, fp);cout << buffer << endl;fclose(fp);/* 字符串轉換long */_counter = strtol(buffer, NULL, 10);cout << "Begin!!! _counter: " << _counter << endl; #endif // 1. 初始化參與者DDS::DomainParticipantFactory_var dpf =TheParticipantFactoryWithArgs(argc, argv);DDS::DomainParticipant_var participant =dpf->create_participant(111,PARTICIPANT_QOS_DEFAULT,DDS::DomainParticipantListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil(participant.in())) {cerr << "create_participant failed." << endl;return 1;}// 2. 注冊數據類型//這里是Topic而不是Topics,意義不同,體現在idl文件里。DemoTopic1TypeSupportImpl* servant = new DemoTopic1TypeSupportImpl();//這句是要根據XXXXTypeSupportImpl中的前綴與idl文件中的Topic key名對應,在這里即"DemoTopic1"OpenDDS::DCPS::LocalObject_var safe_servant = servant;if (DDS::RETCODE_OK != servant->register_type(participant.in(), "")) {cerr << "register_type failed." << endl;exit(1);}// 3. 創建主題CORBA::String_var type_name = servant->get_type_name();DDS::TopicQos topic_qos;participant->get_default_topic_qos(topic_qos);DDS::Topic_var topic =participant->create_topic("Movie Discussion List",type_name.in(),topic_qos,DDS::TopicListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil(topic.in())) {cerr << "create_topic failed." << endl;exit(1);}// 4. 創建公布者DDS::Publisher_var pub =participant->create_publisher(PUBLISHER_QOS_DEFAULT,DDS::PublisherListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil(pub.in())) {cerr << "create_publisher failed." << endl;exit(1);}// 5. 創建數據寫者DDS::DataWriterQos dw_qos;pub->get_default_datawriter_qos(dw_qos);DDS::DataWriter_var dw =pub->create_datawriter(topic.in(),dw_qos,DDS::DataWriterListener::_nil(),::OpenDDS::DCPS::DEFAULT_STATUS_MASK);if (CORBA::is_nil(dw.in())) {cerr << "create_datawriter failed." << endl;exit(1);}DemoTopic1DataWriter_var message_dw //這句是要根據XXXXDataWriter_var,XXXXDataWriter中的前綴與idl文件中的Topic key名對應,在這里即"DemoTopic1"= DemoTopic1DataWriter::_narrow(dw.in());//// Get default Publisher QoS from a DomainParticipant:DDS::PublisherQos pub_qos;DDS::ReturnCode_t ret;ret = participant->get_default_publisher_qos(pub_qos);if (DDS::RETCODE_OK != ret) {std::cerr << "Could not get default publisher QoS" << std::endl;}// Get default Subscriber QoS from a DomainParticipant:DDS::SubscriberQos sub_qos;ret = participant->get_default_subscriber_qos(sub_qos);if (DDS::RETCODE_OK != ret) {std::cerr << "Could not get default subscriber QoS" << std::endl;}// Get default Topic QoS from a DomainParticipant:DDS::TopicQos topic_qos2;ret = participant->get_default_topic_qos(topic_qos2);if (DDS::RETCODE_OK != ret) {std::cerr << "Could not get default topic QoS" << std::endl;}// Get default DomainParticipant QoS from a DomainParticipantFactory:DDS::DomainParticipantQos dp_qos;ret = dpf->get_default_participant_qos(dp_qos);if (DDS::RETCODE_OK != ret) {std::cerr << "Could not get default participant QoS" << std::endl;}// Get default DataWriter QoS from a Publisher:DDS::DataWriterQos dw_qos2;ret = pub->get_default_datawriter_qos(dw_qos2);if (DDS::RETCODE_OK != ret) {std::cerr << "Could not get default data writer QoS" << std::endl;}// 6. 公布數據DemoTopic1 message;//這句是要根據idl文件中的Topic key名對應,在這里即"DemoTopic1"message.id = 99;::DDS::InstanceHandle_t handle = message_dw->register_instance(message);// message.counter = 0; #if 1message.counter = _counter;cout << " RETT-message!!!: " << message.counter << endl; #endifchar tMsg[50] = { 0 };while (1){message.counter++;memset(tMsg, 0, 50);sprintf(tMsg, "RETT-Msg Counter : %d", message.counter);message.text = ::TAO::String_Manager(tMsg);message_dw->write(message, handle);ACE_OS::sleep(1);cout << "RETT..." << endl;cout << "RETT-halo eyeryone!!!" << message.counter << endl;}// 7. 實體清理participant->delete_contained_entities();dpf->delete_participant(participant);TheServiceParticipant->shutdown();}catch (CORBA::Exception& e){cerr << "PUB: Exception caught in main.cpp:" << endl<< e << endl;exit(1);}return 0; }2. Subscriber.cpp
/* 1. 初始化參與者
2. 注冊數據類型并創建主題
3. 創建訂閱者
4. 創建監聽者
5. 創建數據讀者
6. 清理與OpenDDS相關聯的資源*/
3. DataReaderListener.h
// 數據讀者監聽者實現 #ifndef DATAREADER_LISTENER_IMPL #define DATAREADER_LISTENER_IMPL#include <dds/DdsDcpsSubscriptionExtC.h> #include <dds/DCPS/LocalObject.h>#if !defined (ACE_LACKS_PRAGMA_ONCE) #pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */class DataReaderListener: public virtual OpenDDS::DCPS::LocalObject<OpenDDS::DCPS::DataReaderListener> { public:DataReaderListener();virtual ~DataReaderListener(void);virtual void on_requested_deadline_missed(DDS::DataReader_ptr reader,const DDS::RequestedDeadlineMissedStatus& status);virtual void on_requested_incompatible_qos(DDS::DataReader_ptr reader,const DDS::RequestedIncompatibleQosStatus& status);virtual void on_liveliness_changed(DDS::DataReader_ptr reader,const DDS::LivelinessChangedStatus& status);virtual void on_subscription_matched(DDS::DataReader_ptr reader,const DDS::SubscriptionMatchedStatus& status);virtual void on_sample_rejected(DDS::DataReader_ptr reader,const DDS::SampleRejectedStatus& status);virtual void on_data_available(DDS::DataReader_ptr reader);virtual void on_sample_lost(DDS::DataReader_ptr reader,const DDS::SampleLostStatus& status);virtual void on_subscription_disconnected(DDS::DataReader_ptr reader,const ::OpenDDS::DCPS::SubscriptionDisconnectedStatus& status);virtual void on_subscription_reconnected(DDS::DataReader_ptr reader,const ::OpenDDS::DCPS::SubscriptionReconnectedStatus& status);virtual void on_subscription_lost(DDS::DataReader_ptr reader,const ::OpenDDS::DCPS::SubscriptionLostStatus& status);virtual void on_budget_exceeded(DDS::DataReader_ptr reader,const ::OpenDDS::DCPS::BudgetExceededStatus& status);long num_reads() const {return num_reads_;}private:DDS::DataReader_var reader_;long num_reads_; };#endif /* DATAREADER_LISTENER_IMPL */4. DataReaderListener.cpp
// -*- C++ -*- // #include "DataReaderListener.h" #include "DemoTypeSupportC.h" #include "DemoTypeSupportImpl.h" #include <dds/DCPS/Service_Participant.h> #include <ace/streams.h>using namespace DemoIdlModule;DataReaderListener::DataReaderListener(): num_reads_(0) { }DataReaderListener::~DataReaderListener() { }void DataReaderListener::on_data_available(DDS::DataReader_ptr reader) {++num_reads_;//0. 文件FILE* fp;//char c[] = "The counter is: 5";char c[50] = "2";char buffer[50] = { 0 };long _counter = 0;/* 打開文件用于讀寫 */if (fp = fopen("F:\\J18-ZaiJian\\BBB.txt", "w+"))cout << "RETT-Open file success--- ";try {DemoTopic1DataReader_var message_dr = DemoTopic1DataReader::_narrow(reader);if (CORBA::is_nil(message_dr.in())) {cerr << "read: _narrow failed." << endl;exit(1);}DemoTopic1 message;DDS::SampleInfo si;DDS::ReturnCode_t status = message_dr->take_next_sample(message, si);if (status == DDS::RETCODE_OK) {cout << "PP-Message: id = " << message.id << endl<< " PP-DemoTopic1_Counter = " << message.counter << endl<< " PP-DemoTopic1_Text = " << message.text << endl;cout << "SampleInfo.sample_rank = " << si.sample_rank << endl;_counter = message.counter;}else if (status == DDS::RETCODE_NO_DATA) {cerr << "ERROR: reader received DDS::RETCODE_NO_DATA!" << endl;}else {cerr << "ERROR: read Message: Error: " << status << endl;}}catch (CORBA::Exception& e) {cerr << "Exception caught in read:" << endl << e << endl;exit(1);}ltoa(_counter, c, 10);/* 寫入數據到文件 */fwrite(c, strlen(c) + 1, 1, fp);/* 查找文件的開頭 */fseek(fp, 0, SEEK_SET);/* 讀取并顯示數據 */fread(buffer, strlen(c) + 1, 1, fp);cout << buffer << endl;fclose(fp); }void DataReaderListener::on_requested_deadline_missed(DDS::DataReader_ptr,const DDS::RequestedDeadlineMissedStatus&) {cerr << "DataReaderListener::on_requested_deadline_missed" << endl; }void DataReaderListener::on_requested_incompatible_qos(DDS::DataReader_ptr,const DDS::RequestedIncompatibleQosStatus&) {cerr << "DataReaderListener::on_requested_incompatible_qos" << endl; }void DataReaderListener::on_liveliness_changed(DDS::DataReader_ptr,const DDS::LivelinessChangedStatus&) {cerr << "DataReaderListener::on_liveliness_changed" << endl; }void DataReaderListener::on_subscription_matched(DDS::DataReader_ptr,const DDS::SubscriptionMatchedStatus&) {cerr << "DataReaderListener::on_subscription_matched" << endl; }void DataReaderListener::on_sample_rejected(DDS::DataReader_ptr,const DDS::SampleRejectedStatus&) {cerr << "DataReaderListener::on_sample_rejected" << endl; }void DataReaderListener::on_sample_lost(DDS::DataReader_ptr,const DDS::SampleLostStatus&) {cerr << "DataReaderListener::on_sample_lost" << endl; }void DataReaderListener::on_subscription_disconnected(DDS::DataReader_ptr,const ::OpenDDS::DCPS::SubscriptionDisconnectedStatus&) {cerr << "DataReaderListener::on_subscription_disconnected" << endl; }void DataReaderListener::on_subscription_reconnected(DDS::DataReader_ptr,const ::OpenDDS::DCPS::SubscriptionReconnectedStatus&) {cerr << "DataReaderListener::on_subscription_reconnected" << endl; }void DataReaderListener::on_subscription_lost(DDS::DataReader_ptr,const ::OpenDDS::DCPS::SubscriptionLostStatus&) {cerr << "DataReaderListener::on_subscription_lost" << endl; }void DataReaderListener::on_budget_exceeded(DDS::DataReader_ptr,const ::OpenDDS::DCPS::BudgetExceededStatus&) {cerr << "DataReaderListener::on_budget_exceeded" << endl; }四、編譯
0)點擊“重新生成解決方案”,重新編譯。
1)編譯完成后,生成exe文件如下:
2)在路徑下新建文件,名稱為:AAA.txt,內容:123
3)把編譯好的程序目錄拷貝到之前已搭建好同樣開發環境的另一臺電腦上。
五、運行(1、對等發現方式;2、集中發現方式)
0.運行前準備
操作如下:用網線連接兩臺電腦。
1.采用對等發現的方式運行:
config_Pub.ini和config_Sub.ini配置文件內容基本一樣為:
1).如圖:分別在兩臺電腦上,不分先后的運行一個Publisher或Subscriber實例,
a)一臺電腦,執行命令如下:
2). 當然,對等發現方式其實只需要執行./Publisher和./Subscriber,
默認就會去找config_Pub.ini和config_Sub.ini
2. 另外,還有另一種方式,采用集中發現的方式運行:(請查看后面的筆記)
config_Pub.ini和config_Sub.ini配置文件內容基本一樣為:
六、具體的集中發現的方式運行(比較繁瑣)
操作如下:用網線連接兩臺電腦。
1)雙方電腦安裝DUKTO. 然后筆記本電腦將編譯成功的工程目錄F:\J18-ZaiJian\ZJ-DDS-220301全部拷貝到臺式電腦中.路徑地址都是F:\J18-ZaiJian\ZJ-DDS-220301 2)設置IP地址,并確保防火墻全部關閉。必須先確保網絡通信沒有問題。 3)確保臺式電腦的開發環境\環境變量及路徑與筆記本電腦的設置是一樣的。配置環境變量和路徑的具體步驟請參考文章《OpenDDS環境搭建-Windows 10》.https://blog.csdn.net/babypphappy/article/details/123228108A端訂閱—臺式電腦的操作如下:(確保開發環境\環境變量及路徑都設置完畢)
臺式電腦的IP位:192.168.2.112
ipconfig //查看本機IP地址,確保設置為192.168.2.112,
打開vs2017開發人員命令行提示符: 看能否ping通筆記本電腦.
1)打開vs2017開發人員命令行提示符,先setenv.cmd
然后開啟DCPS服務
%DDS_ROOT%/bin/DCPSInfoRepo -ORBListenEndpoints iiop://192.168.2.112:651232)再打開vs2017開發人員命令行提示符,先setenv.cmd
%DDS_ROOT%\setenv.cmd然后執行:訂閱
subscriber -DCPSInfoRepo corbaloc::192.168.2.112:65123/DCPSInfoRepoB端發布—筆記本電腦的操作如下:(確保開發環境\環境變量及路徑都設置完畢)
筆記本電腦的IP位:192.168.2.110
ipconfig//查看筆記本電腦本機IP地址,確保設置為192.168.2.110
打開vs2017開發人員命令行提示符: 看能否ping通臺式電腦ip
兩臺電腦互ping能通成功后,打開vs2017開發人員命令行提示符。
1)先setenv.cmd【總結】運行OPenDDS例程(采用集中發現的方式)
(F:\J18-ZaiJian\ZJ-DDS-220301)
兩臺電腦操作如下運行測試(開發人員命令行提示符:vs2017和vs2019自帶的命令行)
☆☆.必須關閉雙方所有的防火墻,且確認主機A和主機B能夠ping通.☆☆
主機A:(臺式電腦 IP:192.168.2.112)[記得提前setenv.cmd]
主機B:(筆記本電腦 IP:192.168.2.110)[記得提前setenv.cmd]
publisher -DCPSInfoRepo corbaloc::192.168.2.112:65123/DCPSInfoRepo總結
以上是生活随笔為你收集整理的OPenDDS程序 的 实现+运行的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 随手小记·080911
- 下一篇: Linux-Android 修改屏蔽长按