Fast-DDS 接收数据完整时序分析
⚠️ 重要声明
本文档基于 Fast-DDS 特定 commit 版本分析,代码接口可能随版本演进发生变化。
- Commit ID :
5d3acdcba3f57391ad08b2739b09e70f3a2492ea- Commit Date: 2026-02-26
- Branch: master / origin/3.5.x
- Author : Raül Ojeda Gandia raulojeda@eprosima.com
阅读建议: 如遇到接口不匹配,请检查当前代码版本与上述 commit 的差异。
文档说明: 本文档详细分析 Fast-DDS (eProsima Fast DDS v3.5.0) 从网络层接收到应用层获取数据的完整调用流程,包含三层架构、关键分支机制、以及 Listener 模式的数据获取原理。
📋 目录
- 总体架构概览
- 第一层:网络传输层
- [第二层:RTPS 协议解析层](#第二层:RTPS 协议解析层)
- [第三层:DDS 应用层](#第三层:DDS 应用层)
- [Listener 模式详解](#Listener 模式详解)
- 高性能优化机制
- 完整时序图
- 关键代码位置索引
1. 总体架构概览
Fast-DDS 的接收数据流程采用三层架构设计,每层职责清晰,通过模块化实现高可扩展性:
┌─────────────────────────────────────────────────────────────┐
│ Network Layer (网络层) │
│ ASIO Socket → UDP/TCP Transport → Channel Resource │
└──────────────────────────┬──────────────────────────────────┘
│ 原始数据包
▼
┌─────────────────────────────────────────────────────────────┐
│ RTPS Protocol Layer (协议层) │
│ MessageReceiver → 三处关键分支 → Stateful/StatelessReader │
└──────────────────────────┬──────────────────────────────────┘
│ CacheChange_t
▼
┌─────────────────────────────────────────────────────────────┐
│ DDS Application Layer (应用层) │
│ DataReaderImpl → History 管理 → Listener 回调 → 用户代码 │
└─────────────────────────────────────────────────────────────┘
核心设计理念
| 设计原则 | 说明 |
|---|---|
| 分层解耦 | 网络、协议、应用三层独立,便于扩展和维护 |
| 通知与获取分离 | on_data_available() 仅通知,take() 主动获取数据 |
| 命令模式封装 | ReadTakeCommand 统一处理复杂的 read/take 逻辑 |
| 高性能优化 | 栈上分配、零拷贝支持、线程安全锁机制 |
2. 第一层:网络传输层
2.1 数据接收流程
网络层负责从物理网络接收原始数据包,并通过 ASIO 异步 IO 传递给上层。
调用链路
Network Packet
↓
ASIO Socket::recv_from()
↓
UDPChannelResource::perform_listen_operation()
↓
ReceiverResource::OnDataReceived(buffer, length, input_locator, remote_locator)
关键代码
文件位置 : src/cpp/rtps/transport/UDPChannelResource.cpp:61-87
cpp
// UDPChannelResource::perform_listen_operation()
void UDPChannelResource::perform_listen_operation(Locator input_locator)
{
Locator remote_locator;
// 在独立线程中循环接收数据
while (alive())
{
// 同步阻塞接收(Blocking receive)
auto& msg = message_buffer();
if (!Receive(msg.buffer, msg.max_size, msg.length, remote_locator))
{
continue; // 接收失败,继续下一次循环
}
// 通过 CDR Message 接口处理数据
if (message_receiver() != nullptr)
{
// 调用 ReceiverResource 处理
message_receiver()->OnDataReceived(
msg.buffer,
msg.length,
input_locator, // 本地监听地址
remote_locator); // 远程发送者地址
}
else if (alive())
{
EPROSIMA_LOG_WARNING(RTPS_MSG_IN, "Received Message, but no receiver attached");
}
}
message_receiver(nullptr);
}
// UDPChannelResource::Receive() - 底层同步接收实现
bool UDPChannelResource::Receive(
octet* receive_buffer,
uint32_t receive_buffer_capacity,
uint32_t& receive_buffer_size,
Locator& remote_locator)
{
try
{
asio::ip::udp::endpoint senderEndpoint;
// 同步阻塞调用 ASIO 的 receive_from
size_t bytes = socket()->receive_from(
asio::buffer(receive_buffer, receive_buffer_capacity),
senderEndpoint);
receive_buffer_size = static_cast<uint32_t>(bytes);
if (receive_buffer_size > 0)
{
// 将 ASIO endpoint 转换为 Fast-DDS Locator
transport_->endpoint_to_locator(senderEndpoint, remote_locator);
}
return (receive_buffer_size > 0);
}
catch (const std::exception& error)
{
EPROSIMA_LOG_WARNING(RTPS_MSG_OUT, "Error receiving data: " << error.what());
return false;
}
}
关键点:
- ✅ 使用独立线程 运行
perform_listen_operation() - ✅ 采用同步阻塞 方式调用
socket()->receive_from() - ✅ 通过
while(alive())循环持续接收数据 - ✅ 接收成功后调用
OnDataReceived()传递给 RTPS 层
3. 第二层:RTPS 协议解析层
RTPS 层是 Fast-DDS 的核心,负责解析 DDS 标准定义的 RTPS 协议消息。该层包含三处关键分支,决定了数据的处理路径。
3.1 入口函数:MessageReceiver::processCDRMsg()
文件位置 : src/cpp/rtps/messages/MessageReceiver.cpp:250-500
cpp
bool MessageReceiver::processCDRMsg(
const Locator_t& source_locator,
const Locator_t& remote_locator,
const octet* buffer,
size_t buffer_size)
{
// 1. 解析 RTPS 头部
CDRMessage_t msg;
msg.init(buffer, buffer_size);
RTPSMessageHeader_t header;
if (!CDRMessage::readRTPSMessageHeader(&msg, &header))
{
return false;
}
// 2. 循环解析子消息
while (msg.pos < msg.length)
{
SubmessageHeader_t submsg_header;
CDRMessage::readSubmessageHeader(&msg, &submsg_header);
// 【分支1】根据子消息类型分发
switch (submsg_header.submessageId)
{
case DATA:
proc_Submsg_Data(&msg, &submsg_header, ...);
break;
case DATA_FRAG:
proc_Submsg_DataFrag(&msg, &submsg_header, ...);
break;
case HEARTBEAT:
proc_Submsg_Heartbeat(&msg, &submsg_header, ...);
break;
case ACKNACK:
proc_Submsg_Acknack(&msg, &submsg_header, ...);
break;
case GAP:
proc_Submsg_Gap(&msg, &submsg_header, ...);
break;
// ... 其他子消息类型
}
}
return true;
}
3.2 【分支1】子消息类型分发
决策依据: RTPS 协议定义的子消息 ID
| 子消息类型 | 处理函数 | 作用 |
|---|---|---|
DATA |
proc_Submsg_Data() |
处理完整数据样本 |
DATA_FRAG |
proc_Submsg_DataFrag() |
处理分片数据 |
HEARTBEAT |
proc_Submsg_Heartbeat() |
可靠性心跳(RELIABLE 模式) |
ACKNACK |
proc_Submsg_Acknack() |
确认/否定确认(RELIABLE 模式) |
GAP |
proc_Submsg_Gap() |
序列号间隙通知 |
INFO_SRC |
proc_Submsg_InfoSRC() |
源信息(GUID、版本等) |
INFO_TS |
proc_Submsg_InfoTS() |
时间戳信息 |
设计目的: 支持 RTPS 协议的多种消息类型,实现完整的发布-订阅语义。
3.3 【分支2】安全/非安全路径选择
以 DATA 子消息为例,展示第二处分支:
文件位置 : src/cpp/rtps/messages/MessageReceiver.cpp:68-105
// MessageReceiver 构造函数中初始化函数指针
MessageReceiver::MessageReceiver(RTPSParticipantImpl* participant)
{
#ifdef HAVE_SECURITY
// 启用 DDS Security 标准
process_data_message_function_ =
&MessageReceiver::process_data_message_with_security;
#else
// 非安全模式(默认)
process_data_message_function_ =
&MessageReceiver::process_data_message_without_security;
#endif
}
// proc_Submsg_Data() 解析完 DATA 内容后调用
void MessageReceiver::proc_Submsg_Data(...)
{
// 1. 解析 ReaderID、WriterGUID、SequenceNumber
// 2. 解析 InlineQoS
// 3. 提取 Payload
CacheChange_t change;
change.writerGUID = writer_guid;
change.sequenceNumber = seq_num;
// ... 填充其他字段
// 【分支2】通过函数指针调用
bool was_decoded = false;
process_data_message_function_(reader_id, &change, was_decoded);
}
两条处理路径
路径 A: 非安全模式(默认)
文件位置 : src/cpp/rtps/messages/MessageReceiver.cpp:221-232
cpp
void MessageReceiver::process_data_message_without_security(
const EntityId_t& reader_id,
CacheChange_t* change,
bool& was_decoded)
{
// 直接查找匹配的 Reader
findAllReaders(reader_id, [change, &was_decoded](BaseReader* reader)
{
was_decoded = true;
// 调用 Reader 的处理方法
reader->process_data_msg(change);
});
}
路径 B: 安全模式(启用加密)
文件位置 : src/cpp/rtps/messages/MessageReceiver.cpp:127-167
void MessageReceiver::process_data_message_with_security(
const EntityId_t& reader_id,
CacheChange_t* change,
bool& was_decoded)
{
// 1. 解密 payload
SecurityManager* security_manager = participant_->security_manager();
if (!security_manager->decode_serialized_payload(
change->serializedPayload,
decoded_payload,
change->writerGUID))
{
return; // 解密失败
}
// 2. 替换为解密后的 payload
change->serializedPayload = decoded_payload;
was_decoded = true;
// 3. 查找匹配的 Reader
findAllReaders(reader_id, [change, &was_decoded](BaseReader* reader)
{
reader->process_data_msg(change);
});
}
设计目的:
- ✅ 支持可选的 DDS Security 标准
- ✅ 透明加解密,对上层应用无感知
- ✅ 函数指针分发,避免运行时条件判断开销
3.4 【分支3】Reader 类型多态
文件位置 : src/cpp/rtps/reader/StatefulReader.cpp:567
// BaseReader 定义纯虚函数
class BaseReader
{
public:
virtual bool process_data_msg(CacheChange_t* change) = 0;
};
// StatefulReader 实现(RELIABLE 模式)
bool StatefulReader::process_data_msg(CacheChange_t* change)
{
// 1. 查找或创建 WriterProxy
WriterProxy* pWP = nullptr;
if (!acceptMsgFrom(change->writerGUID, &pWP))
{
return false;
}
// 2. 检查是否已接收过该序列号
if (pWP->change_was_received(change->sequenceNumber))
{
return false; // 重复数据,忽略
}
// 3. 检查 History 是否能接收
if (!history_->can_change_be_added_nts(...))
{
return false;
}
// 4. 检查内容过滤
if (!change_is_relevant_for_filter(change))
{
return false;
}
// 5. 从 pool 获取 CacheChange
CacheChange_t* change_to_add = nullptr;
if (!change_pool_->reserve_cache(&change_to_add))
{
return false;
}
// 6. 拷贝元数据
change_to_add->copy_not_memcpy(change);
// 7. 获取 payload
if (!payload_pool_->get_payload(...))
{
change_pool_->release_cache(change_to_add);
return false;
}
// 8. 添加到 History 并通知
change_received(change_to_add, pWP, unknown_missing_changes_up_to);
return true;
}
// StatelessReader 实现(BEST_EFFORT 模式)
bool StatelessReader::process_data_msg(CacheChange_t* change)
{
// 简化流程:不维护 WriterProxy 状态
// 直接添加到 History
history_->add_change(change);
listener_->onNewCacheChangeAdded(this, change);
return true;
}
两种 Reader 对比
| 特性 | StatefulReader | StatelessReader |
|---|---|---|
| QoS 策略 | RELIABLE(可靠) | BEST_EFFORT(尽力而为) |
| 状态管理 | 维护 WriterProxy,跟踪序列号 | 无状态 |
| 重传支持 | ✅ 支持(通过 HEARTBEAT/ACKNACK) | ❌ 不支持 |
| 性能 | 较低(需维护状态) | 较高(无状态开销) |
| 适用场景 | 关键数据传输 | 高频传感器数据 |
设计目的:
- ✅ 通过虚函数多态支持不同的可靠性策略
- ✅ 应用层无需关心底层实现细节
- ✅ 符合开闭原则,易于扩展新的 Reader 类型
4. 第三层:DDS 应用层
DDS 层负责将 RTPS 层的原始数据转换为应用层可用的对象,并提供丰富的 QoS 策略和监听机制。
4.1 添加到 History
文件位置 : src/cpp/rtps/reader/StatefulReader.cpp:1085-1230
cpp
bool StatefulReader::change_received(
CacheChange_t* a_change,
WriterProxy* pWP,
size_t unknown_missing_changes_up_to)
{
// 1. 更新 WriterProxy 状态
pWP->received_change_set(a_change->sequenceNumber);
// 2. 添加到 History
if (!history_->received_change(a_change, unknown_missing_changes_up_to))
{
change_pool_->release_cache(a_change);
return false;
}
// 3. 通知 Listener
NotifyChanges(pWP);
return true;
}
ReaderHistory::received_change() 内部逻辑:
cpp
bool ReaderHistory::received_change(CacheChange_t* a_change, ...)
{
// 1. 查找或创建 Instance
InstanceHandle_t instance_handle = find_or_create_instance(a_change);
// 2. 根据 History QoS 策略决定如何处理
switch (qos_.history().kind)
{
case KEEP_LAST_HISTORY_QOS:
// 保留最近 N 个样本(N = depth)
if (instance->get_change_count() >= qos_.history().depth)
{
remove_oldest_change(instance);
}
break;
case KEEP_ALL_HISTORY_QOS:
// 保留所有样本(受资源限制)
break;
}
// 3. 添加样本到实例
instance->add_change(a_change);
return true;
}
4.2 RTPS 层 → DDS 层桥接
文件位置 : src/cpp/rtps/reader/StatefulReader.cpp:1236-1300
void StatefulReader::NotifyChanges(WriterProxy* prox)
{
auto listener = get_listener();
if (nullptr != listener)
{
bool notify_individual = false;
// 计算序列号范围
SequenceNumber_t first_seq = ...;
SequenceNumber_t max_seq = ...;
// 调用 RTPS ReaderListener
listener->on_data_available(
this,
prox->guid(),
first_seq,
max_seq,
notify_individual);
// 如果需要逐个通知
if (notify_individual)
{
auto it = history_->changesBegin();
SequenceNumber_t next_seq = first_seq;
while (next_seq <= max_seq &&
history_->changesEnd() !=
(it = history_->get_change_nts(next_seq, ..., &aux_ch, it)))
{
aux_ch = *it;
next_seq = aux_ch->sequenceNumber + 1;
// 逐个通知新添加的 CacheChange
listener->on_new_cache_change_added(this, aux_ch);
// 重置迭代器(防止回调中失效)
it = history_->changesBegin();
}
}
}
}
4.3 InnerDataReaderListener 桥接
文件位置 : src/cpp/fastdds/subscriber/DataReaderImpl.cpp:924-937
// DataReaderImpl 内部监听器,负责 RTPS → DDS 转换
void DataReaderImpl::InnerDataReaderListener::on_data_available(
RTPSReader* /*reader*/,
const GUID_t& writer_guid,
const SequenceNumber_t& first_sequence,
const SequenceNumber_t& last_sequence,
bool& should_notify_individual_changes)
{
should_notify_individual_changes = false;
// 调用 DataReaderImpl 的处理逻辑
if (data_reader_->on_data_available(
writer_guid, first_sequence, last_sequence))
{
// 设置通信状态标志,触发用户 Listener
data_reader_->set_read_communication_status(true);
}
}
4.4 DataReaderImpl::on_data_available()
文件位置 : src/cpp/fastdds/subscriber/DataReaderImpl.cpp:1063-1083
bool DataReaderImpl::on_data_available(
const GUID_t& writer_guid,
const SequenceNumber_t& first_sequence,
const SequenceNumber_t& last_sequence)
{
bool ret_val = false;
// 加锁保护
std::lock_guard<RecursiveTimedMutex> guard(reader_->getMutex());
// 遍历序列号范围,更新每个样本的状态
for (auto seq = first_sequence; seq <= last_sequence; ++seq)
{
CacheChange_t* change = nullptr;
if (history_.get_change(seq, writer_guid, &change))
{
// 更新实例状态、Deadline、Lifespan 等
ret_val |= on_new_cache_change_added(change);
}
}
// 通知 ReadCondition(用于 WaitSet)
try_notify_read_conditions();
return ret_val;
}
4.5 触发用户 Listener 回调
文件位置 : src/cpp/fastdds/subscriber/DataReaderImpl.cpp:384-413
void DataReaderImpl::set_read_communication_status(bool trigger_value)
{
if (trigger_value)
{
auto user_reader = user_datareader_;
// 1. 先检查 Subscriber 级别的监听器
SubscriberListener* subscriber_listener =
subscriber_->get_listener_for(StatusMask::data_on_readers());
if (subscriber_listener != nullptr)
{
// Subscriber 级别优先处理
subscriber_listener->on_data_on_readers(
subscriber_->user_subscriber_);
}
else
{
// 2. 调用 DataReader 级别的监听器 ← 关键!
DataReaderListener* listener =
get_listener_for(StatusMask::data_available());
if (listener != nullptr)
{
// 这就是用户定义的 ListenerSubscriberApp::on_data_available()
listener->on_data_available(user_reader);
}
}
}
// 3. 设置状态标志(用于 WaitSet 机制)
StatusMask notify_status = StatusMask::data_on_readers();
subscriber_->user_subscriber_->get_statuscondition()
->get_impl()->set_status(notify_status, trigger_value);
notify_status = StatusMask::data_available();
user_datareader_->get_statuscondition()
->get_impl()->set_status(notify_status, trigger_value);
}
关键点:
- ✅ 支持两级 Listener:Subscriber 级和 DataReader 级
- ✅ Subscriber 级优先(
on_data_on_readers) - ✅ 同时设置状态标志,支持 WaitSet 机制
5. Listener 模式详解
5.1 通知与获取分离的设计哲学
Fast-DDS 采用通知与获取分离的设计,这是理解 Listener 模式的关键。
两个核心环节
| 环节 | 函数 | 职责 | 触发方式 |
|---|---|---|---|
| 通知 | on_data_available(reader) |
告知应用"有数据到达" | 框架自动触发 |
| 获取 | reader->take_next_sample() |
从 History 取出实际数据 | 用户主动调用 |
为什么这样设计?
- 灵活性: 应用可以决定何时、如何获取数据
- 批量处理 : 可以在回调中使用
while循环一次性读取多个样本 - 错误处理 : 可以检查
take()的返回值,处理异常情况 - 零拷贝支持: 可以使用 loaned samples 避免内存拷贝
5.2 HelloWorld 示例代码分析
文件位置 : examples/cpp/hello_world/ListenerSubscriberApp.cpp:127-142
// 1. 创建 DataReader 时注册 Listener
reader_ = subscriber_->create_datareader(
topic_,
reader_qos,
this, // ← 传入 this 作为 Listener
StatusMask::all());
// 2. 用户定义的回调函数
void ListenerSubscriberApp::on_data_available(DataReader* reader)
{
SampleInfo info;
// 3. 在回调中主动调用 take_next_sample 获取数据
while ((!is_stopped()) &&
(RETCODE_OK == reader->take_next_sample(&hello_, &info)))
{
if ((info.instance_state == ALIVE_INSTANCE_STATE) && info.valid_data)
{
received_samples_++;
// 4. 处理数据
std::cout << "Message: '" << hello_.message()
<< "' with index: '" << hello_.index()
<< "' RECEIVED" << std::endl;
if (samples_ > 0 && (received_samples_ >= samples_))
{
stop();
}
}
}
}
关键要点
❌ 常见误解 : 认为 on_data_available() 会直接传递数据
✅ 实际情况 : on_data_available() 只是通知信号,必须主动调用 take() 获取数据
5.3 串联关系图解
┌─────────────────────────────────────────────────────────┐
│ RTPS 层: StatefulReader::NotifyChanges() │
│ ↓ │
│ 调用 InnerDataReaderListener::on_data_available() │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ DDS 层: DataReaderImpl::on_data_available() │
│ ↓ │
│ 调用 set_read_communication_status(true) │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 触发用户回调 │
│ ↓ │
│ listener->on_data_available(user_reader) │
│ ↓ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ 用户代码: ListenerSubscriberApp │ │
│ │ │ │
│ │ void on_data_available(DataReader* reader) { │ │
│ │ // 此时还没有数据! │ │
│ │ │ │
│ │ // 必须主动调用 take_next_sample │ │
│ │ while(reader->take_next_sample(&hello_, │ │
│ │ &info)) { │ │
│ │ // 现在才有数据 │ │
│ │ cout << hello_.message(); │ │
│ │ } │ │
│ │ } │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
6. 高性能优化机制
6.1 栈上分配:StackAllocatedSequence
文件位置 : src/cpp/fastdds/subscriber/DataReaderImpl.cpp:763-765
// 传统方式(堆分配)
std::vector<void*> data_values(1); // malloc + 可能的扩容
// Fast-DDS 优化(栈上分配)
StackAllocatedSequence<void*, 1> data_values; // 栈上固定容量
const_cast<void**>(data_values.buffer())[0] = data;
优势:
- ✅ 避免
new/malloc系统调用开销 - ✅ 确定性内存布局,提高缓存命中率
- ✅ 自动生命周期管理,无需手动释放
适用场景: 单样本或少量样本的高频操作
6.2 命令模式:ReadTakeCommand
文件位置 : src/cpp/fastdds/subscriber/DataReaderImpl/ReadTakeCommand.hpp
// 创建命令对象
detail::StateFilter states{ NOT_READ_SAMPLE_STATE, ANY_VIEW_STATE, ANY_INSTANCE_STATE };
detail::ReadTakeCommand cmd(
*this, // DataReaderImpl 引用
data_values, // 数据缓冲区
sample_infos, // 元信息缓冲区
1, // max_samples
states, // 状态过滤器
it.second, // 实例句柄
false, // exact_instance
false); // single_instance
// 执行命令
while (!cmd.is_finished())
{
cmd.add_instance(should_take); // should_take=true 表示 take
}
封装的复杂逻辑:
- 多实例遍历
- 内容过滤(QueryCondition)
- QoS 策略应用(Deadline、Lifespan 等)
- 资源限制检查
- read/take 语义统一
设计优势:
- ✅ 单一职责:命令对象专注数据获取逻辑
- ✅ 可扩展:易于添加新的过滤条件或 QoS 策略
- ✅ 可测试:命令对象可独立单元测试
6.3 线程安全:递归互斥锁
文件位置 : src/cpp/fastdds/subscriber/DataReaderImpl.cpp:750-752
#if HAVE_STRICT_REALTIME
// 严格实时模式:带超时时间的尝试锁定
auto max_blocking_time = std::chrono::steady_clock::now() +
std::chrono::microseconds(
::TimeConv::Time_t2MicroSecondsInt64(
qos_.reliability().max_blocking_time));
std::unique_lock<RecursiveTimedMutex> lock(
reader_->getMutex(), std::defer_lock);
if (!lock.try_lock_until(max_blocking_time))
{
return RETCODE_TIMEOUT;
}
#else
// 普通模式:直接锁定
std::lock_guard<RecursiveTimedMutex> _(reader_->getMutex());
#endif
特点:
- ✅ 递归锁:允许同一线程多次锁定(避免死锁)
- ✅ 超时控制:严格实时模式下符合 QoS 要求
- ✅ 细粒度锁定:仅保护 History 访问,不影响其他操作
6.4 read vs take 语义对比
| 操作 | 行为 | History 变化 | 适用场景 |
|---|---|---|---|
| read | 复制样本数据 | 样本保留,标记为已读 | 需要多次读取或 peek 数据 |
| take | 复制样本数据 | 样本从 History 移除 | 数据处理后不再需要 |
示例:
// read: 数据仍在 History 中
reader->read_next_sample(&data, &info); // 可以再次 read
// take: 数据从 History 移除
reader->take_next_sample(&data, &info); // 不能再次 take
7. 完整时序图
7.1 简化版时序图
Publisher → Network → ASIO → UDPChannel
↓
ReceiverResource::OnDataReceived()
↓
MessageReceiver::processCDRMsg()
↓
【分支1】switch(submessageId)
↓
【分支2】安全/非安全路径
↓
【分支3】Stateful/Stateless Reader
↓
StatefulReader::change_received()
↓
history_->received_change()
↓
NotifyChanges()
↓
InnerDataReaderListener::on_data_available()
↓
DataReaderImpl::on_data_available()
↓
set_read_communication_status(true)
↓
listener->on_data_available(reader) ← 用户回调
↓
reader->take_next_sample(&data, &info) ← 用户主动获取
↓
ReadTakeCommand::add_instance()
↓
从 History 取出 + 反序列化 CDR
↓
用户处理数据
7.2 详细版时序图(含组件交互)
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐
│Publisher │ │ Network │ │ ASIO │ │UDPChannel │
│ │ │ │ │ Socket │ │Resource │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘
│ │ │ │
│──write()──▶ │ │ │
│ │──Packet──▶ │ │
│ │ │──recv_from()──▶ │
│ │ │ │
│ │ │ │──OnDataReceived()──▶
│ │ │ │
┌────▼───────────────▼───────────────▼──────────────────▼──────────────┐
│ RTPS Protocol Layer │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ MessageReceiver::processCDRMsg() │ │
│ │ ├─ 解析 RTPS 头部 │ │
│ │ └─ 【分支1】switch(submessageId) │ │
│ │ └─ DATA → proc_Submsg_Data() │ │
│ │ ↓ │ │
│ │ 【分支2】process_data_message_function_ │ │
│ │ └─ findAllReaders() │ │
│ │ ↓ │ │
│ │ 【分支3】BaseReader::process_data_msg() (多态) │ │
│ │ └─ StatefulReader::process_data_msg() │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ StatefulReader::change_received() │ │
│ │ ├─ acceptMsgFrom() → WriterProxy │ │
│ │ ├─ change_pool_->reserve_cache() │ │
│ │ ├─ payload_pool_->get_payload() │ │
│ │ └─ history_->received_change() │ │
│ │ ↓ │ │
│ │ NotifyChanges() │ │
│ │ ↓ │ │
│ │ InnerDataReaderListener::on_data_available() │ │
│ └──────────────────────────────────────────────────────────────┘ │
└──────────────────────────────┬──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────┐
│ DDS Application Layer │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ DataReaderImpl::on_data_available() │ │
│ │ ├─ on_new_cache_change_added() → 更新实例状态 │ │
│ │ └─ set_read_communication_status(true) │ │
│ │ ↓ │ │
│ │ 【触发用户回调】 │ │
│ │ listener->on_data_available(user_datareader_) │ │
│ │ ↓ │ │
│ │ ┌──────────────────────────────────────────────────────┐ │ │
│ │ │ 用户代码: ListenerSubscriberApp │ │ │
│ │ │ │ │ │
│ │ │ void on_data_available(DataReader* reader) { │ │ │
│ │ │ while(reader->take_next_sample(&hello_, &info)){│ │ │
│ │ │ // 处理数据 │ │ │
│ │ │ } │ │ │
│ │ │ } │ │ │
│ │ └──────────────────────────────────────────────────────┘ │ │
│ │ ↓ │ │
│ │ DataReaderImpl::read_or_take_next_sample() │ │
│ │ ├─ 加锁 (RecursiveTimedMutex) │ │
│ │ ├─ lookup_available_instance() │ │
│ │ ├─ ReadTakeCommand 执行 take 操作 │ │
│ │ │ ├─ 从 History 取出 CacheChange │ │
│ │ │ ├─ 反序列化 CDR 数据 │ │
│ │ │ └─ 填充 SampleInfo │ │
│ │ └─ try_notify_read_conditions() │ │
│ └──────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
8. 关键代码位置索引
网络层
| 文件 | 行号 | 函数 | 说明 |
|---|---|---|---|
src/cpp/rtps/transport/UDPChannelResource.cpp |
78 | perform_listen_operation() |
ASIO 异步接收 |
src/cpp/rtps/network/ReceiverResource.h |
53-57 | OnDataReceived() |
传递给 RTPS 层 |
RTPS 协议层
分支 1:子消息分发
| 文件 | 行号 | 函数 | 说明 |
|---|---|---|---|
src/cpp/rtps/messages/MessageReceiver.cpp |
420-580 | processCDRMsg() |
主解析函数 |
src/cpp/rtps/messages/MessageReceiver.cpp |
740-900 | proc_Submsg_Data() |
DATA 消息处理 |
分支 2:安全/非安全
| 文件 | 行号 | 函数 | 说明 |
|---|---|---|---|
src/cpp/rtps/messages/MessageReceiver.cpp |
68-105 | 构造函数 | 函数指针初始化 |
src/cpp/rtps/messages/MessageReceiver.cpp |
221-232 | process_data_message_without_security() |
非安全路径 |
src/cpp/rtps/messages/MessageReceiver.cpp |
127-167 | process_data_message_with_security() |
安全路径 |
分支 3:Reader 多态
| 文件 | 行号 | 函数 | 说明 |
|---|---|---|---|
src/cpp/rtps/reader/StatefulReader.cpp |
567-700 | process_data_msg() |
RELIABLE 实现 |
src/cpp/rtps/reader/StatelessReader.cpp |
- | process_data_msg() |
BEST_EFFORT 实现 |
src/cpp/rtps/reader/StatefulReader.cpp |
1085-1230 | change_received() |
添加到 History |
src/cpp/rtps/reader/StatefulReader.cpp |
1236-1300 | NotifyChanges() |
通知 Listener |
DDS 应用层
| 文件 | 行号 | 函数 | 说明 |
|---|---|---|---|
src/cpp/fastdds/subscriber/DataReaderImpl.cpp |
924-937 | InnerDataReaderListener::on_data_available() |
RTPS→DDS 桥接 |
src/cpp/fastdds/subscriber/DataReaderImpl.cpp |
1063-1083 | DataReaderImpl::on_data_available() |
更新实例状态 |
src/cpp/fastdds/subscriber/DataReaderImpl.cpp |
384-413 | set_read_communication_status() |
触发用户回调 |
src/cpp/fastdds/subscriber/DataReaderImpl.cpp |
730-780 | read_or_take_next_sample() |
从 History 获取数据 |
examples/cpp/hello_world/ListenerSubscriberApp.cpp |
127-142 | on_data_available() |
用户回调示例 |
9. 总结
核心设计思想
- 三层架构: 网络层、RTPS 协议层、DDS 应用层职责清晰
- 三处分支: 子消息类型、安全配置、可靠性策略决定处理路径
- 通知与获取分离 :
on_data_available()通知,take()主动获取 - 高性能优化: 栈上分配、命令模式、线程安全锁
学习建议
- 从示例入手: 先运行 HelloWorld 示例,观察 Listener 回调
- 逐层深入: 从应用层 → RTPS 层 → 网络层,理解每层职责
- 关注分支: 重点理解三处分支的决策逻辑
- 实践验证: 修改 QoS 策略,观察不同 Reader 的行为差异
延伸阅读
文档版本 : v1.0
最后更新 : 2026-05-17
适用 Fast-DDS 版本: v3.5.0