1. Hello World 发布订阅
任务目标
使用FastDDS创建一个发布者节点和一个订阅者节点,实现字符串消息“Hello World”的单向传输。发布者周期性发送消息,订阅者接收并打印消息内容。
环境依赖
需要安装FastDDS库及其依赖(如Foonathan memory、ASIO等)。推荐使用FastDDS 2.x版本,并确保编译环境支持C++11及以上标准。若使用CMake构建,需在系统中找到FastDDS的安装路径。
核心实现
以下代码包含完整的IDL定义、发布者与订阅者实现。IDL文件用于生成数据类型,发布者创建Publisher并周期发送消息,订阅者创建Subscriber并注册回调函数接收消息。
// HelloWorld.idl
struct HelloWorld
{
string msg;
};
// publisher.cpp
#include <iostream>
#include <thread>
#include <chrono>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/publisher/DataWriterListener.hpp>
#include <fastdds/dds/topic/Topic.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include "HelloWorldPubSubTypes.h"
using namespace eprosima::fastdds::dds;
class PubListener : public DataWriterListener
{
public:
PubListener() : matched(0) {}
void on_publication_matched(DataWriter*, const PublicationMatchedStatus& info) override
{
if (info.current_count_change == 1) matched = info.current_count;
else if (info.current_count_change == -1) matched = info.current_count;
}
int matched;
};
int main()
{
DomainParticipantQos pqos = PARTICIPANT_QOS_DEFAULT;
DomainParticipant* participant = DomainParticipantFactory::get_instance().create_participant(0, pqos);
if (!participant) return 1;
HelloWorldPubSubType type;
TypeSupport ts(&type);
participant->register_type(ts);
Topic* topic = participant->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT);
if (!topic) return 1;
Publisher* publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT);
if (!publisher) return 1;
PubListener listener;
DataWriterQos wqos = DATAWRITER_QOS_DEFAULT;
DataWriter* writer = publisher->create_datawriter(topic, wqos, &listener);
if (!writer) return 1;
HelloWorld sample;
sample.msg("Hello World");
int count = 0;
while (count < 10)
{
if (listener.matched > 0)
{
writer->write(&sample);
std::cout << "Sent: " << sample.msg() << std::endl;
count++;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
participant->delete_contained_entities();
DomainParticipantFactory::get_instance().delete_participant(participant);
return 0;
}
// subscriber.cpp
#include <iostream>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
#include <fastdds/dds/topic/Topic.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include "HelloWorldPubSubTypes.h"
using namespace eprosima::fastdds::dds;
class SubListener : public DataReaderListener
{
public:
void on_data_available(DataReader* reader) override
{
HelloWorld sample;
SampleInfo info;
if (reader->take_next_sample(&sample, &info) == ReturnCode_t::RETCODE_OK)
{
if (info.valid_data)
std::cout << "Received: " << sample.msg() << std::endl;
}
}
};
int main()
{
DomainParticipant* participant = DomainParticipantFactory::get_instance().create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (!participant) return 1;
HelloWorldPubSubType type;
TypeSupport ts(&type);
participant->register_type(ts);
Topic* topic = participant->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT);
if (!topic) return 1;
Subscriber* subscriber = participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
if (!subscriber) return 1;
SubListener listener;
DataReaderQos rqos = DATAREADER_QOS_DEFAULT;
DataReader* reader = subscriber->create_datareader(topic, rqos, &listener);
if (!reader) return 1;
std::this_thread::sleep_for(std::chrono::seconds(15));
participant->delete_contained_entities();
DomainParticipantFactory::get_instance().delete_participant(participant);
return 0;
}
编译与运行
使用FastDDS提供的fastddsgen工具从IDL生成类型支持代码,然后编译两个可执行文件:
fastddsgen HelloWorld.idl
g++ -std=c++11 publisher.cpp HelloWorldPubSubTypes.cxx HelloWorld.cxx -o publisher -lfastdds -lfastcdr
g++ -std=c++11 subscriber.cpp HelloWorldPubSubTypes.cxx HelloWorld.cxx -o subscriber -lfastdds -lfastcdr
先在一个终端运行订阅者,再在另一个终端运行发布者:
./subscriber
./publisher
验证方法
观察订阅者终端是否打印出10条“Received: Hello World”消息。若发布者终端显示“Sent: Hello World”且订阅者同步收到相同内容,则说明发布订阅通信成功。若订阅者无输出,检查两端是否使用相同的Domain ID(本例均为0)和Topic名称(HelloWorldTopic)。