使用笔记
UDP 同步发送堆栈
从write到sendto
UDP接收堆栈
guid prefix
见guid.h, 前4个字节可以判断是否同一个host,前8个字节可以判断是否同一个process
设置自己的ip+端口以及对端的ip+端口
locator按照通信类型分为:
- Multicast locators: 多播
- Unicast locators: 单播
按数据类型分为: - MetaTraffic locators: Used to receive metatraffic information, usually used by built-in endpoints to ‘’‘perform discovery’‘’.
- User locators: Used by the endpoints created by the user to receive user Topic data changes.
自己的ip+端口分为两部分,一部分是DDS内部数据使用的meta traffic, 服务发现使用的就是这个meta traffic的ip+port; 以及user data使用的ip+port
meta traffic: pqos.wire_protocol().builtin.metatrafficUnicastLocatorList
user data: pqos.wire_protocol().default_unicast_locator_list
设置对端的ip+port: qos.wire_protocol().builtin.initialPeersList
well-known ports
https://fast-dds.docs.eprosima.com/en/latest/fastdds/transport/listening_locators.html#well-known-ports
注意metatraffic的多播端口
,只和domain id有关;而metatraffic的单播端口
,为该domain id的多播端口+10+2*participantId.
而user data的多播端口和单播端口为对应的metatraffic端口+1.
走SHM的dump
https://fast-dds.docs.eprosima.com/en/latest/fastdds/transport/shared_memory/shared_memory.html#sharedmemtransportdescriptor
通过TransportDescriptorInterface的rtps_dump_file指定file路径,生成tcmdump格式数据
遇到的坑
participant/subscriber如果定义了listener
participant/subscriber如果定义了listener, 那改participant或subscriber创建的reader的listener不会调用到on_data_available了,源码:
// src/cpp/fastdds/subscriber/DataReaderImpl.cpp
void DataReaderImpl::InnerDataReaderListener::onNewCacheChangeAdded(
RTPSReader* /*reader*/,
const CacheChange_t* const change_in)
{
if (data_reader_->on_new_cache_change_added(change_in))
{
auto user_reader = data_reader_->user_datareader_;
//First check if we can handle with on_data_on_readers
SubscriberListener* subscriber_listener =
data_reader_->subscriber_->get_listener_for(StatusMask::data_on_readers());
if (subscriber_listener != nullptr)
{
subscriber_listener->on_data_on_readers(data_reader_->subscriber_->user_subscriber_);
}
else
{
// If not, try with on_data_available
DataReaderListener* listener = data_reader_->get_listener_for(StatusMask::data_available());
if (listener != nullptr)
{
listener->on_data_available(user_reader);
}
}
data_reader_->set_read_communication_status(true);
}
}
在判断subscriber_listener是否为空时,如果非空则调用了on_data_on_readers了,不会on_data_available了,看get_listener_for的实现:
// src/cpp/fastdds/subscriber/SubscriberImpl.cpp
SubscriberListener* SubscriberImpl::get_listener_for(
const StatusMask& status)
{
if (listener_ != nullptr &&
user_subscriber_->get_status_mask().is_active(status))
{
return listener_;
}
return participant_->get_listener_for(status);
}
看到这里就是那subscriber或更上面的participant的listener。
一方UDP+SHM, 另一方SHM发现不到
当一方配置了UDP+SHM两种transport(例如默认的配置),一方单独为SHM,两方是互相发现不到的,因为对于UDP+SHM两种配置只会有UDP的端口用来服务发现,可以看bool NetworkFactory::getDefaultMetatrafficMulticastLocators
:
SHM传输方式并非fault-tolerance的
https://github.com/eProsima/Fast-DDS/blob/master/doc/design/shared-memory-transport/interprocess_shared_mem.md
主要是进程间的mutex