车载消息中间件FastDDS 源码解析(七)BuiltinProtocols(下)WLP&TypeLookupManager

802 阅读11分钟

目录:

第一篇 一个例子

车载消息中间件FastDDS 源码解析(一)FastDDS 介绍和使用

第二篇fastdds的组成

车载消息中间件FastDDS 源码解析(二)RtpsParticipant的创建(上)

车载消息中间件FastDDS 源码解析(三)RtpsParticipant的创建(中)

车载消息中间件FastDDS 源码解析(四)RtpsParticipant的创建(下)

车载消息中间件FastDDS 源码解析(五)BuiltinProtocols(上)

车载消息中间件FastDDS 源码解析(六)BuiltinProtocols(中)EDP

车载消息中间件FastDDS 源码解析(七)BuiltinProtocols(下)WLP&TypeLookupManager

车载消息中间件FastDDS 源码解析(八)TimedEvent

车载消息中间件FastDDS 源码解析(九)Message

第三篇组网建立连接

pdp建连

车载消息中间件FastDDS 源码解析(十)发送第一条PDP消息(上)

FastDDS 源码解析(十一)发送第一条PDP消息(中)

FastDDS 源码解析(十二)发送第一条PDP消息(下)---异步发送

FastDDS 源码解析(十三)发送第一条PDP消息---跨进程发送

FastDDS 源码解析(十四)接收PDP消息(上)

FastDDS 源码解析(十五)接收PDP消息(下)

FastDDS 源码解析(十六)处理PDP消息——PDP匹配

EDP建连

FastDDS 源码解析(十七)处理PDP消息——EDP匹配

FastDDS 源码解析(十八)EDP阶段发送心跳heartbeat

FastDDS 源码解析(十九)EDP阶段处理heartbeat消息,发送acknack消息

FastDDS 源码解析(二十)处理acknack消息

上两篇介绍的内置的协议(EDP,PDP)默认都会配置。 这一篇介绍的协议默认是不会配置的,只是在有需要的时候才会配置。

1.WLP简介:

WLP:

image-20240414161836134.png WLP :全称Writer Liveliness Protocol,其实就是和writer 保活相关的协议。我们知道socket 都有心跳来检测网络的稳定性和可靠性,wlp的功能和socket 的心跳机制比较类似,也是管理本地和远端writer状态的协议。当然整个wlp比心跳机制要复杂很多。我们这里只是介绍一下wlp的组成部分。具体的运行机制会在后面详细介绍。

WLP 包含 一个StatefulWriter(RTPSPARTICIPANT_MESSAGE_WRITER 简称 RTPSMsgWriter,对应的就是wlp的mp_builtinWriter属性) 和 一个StatefulReader (RTPSPARTICIPANT_MESSAGE_READER 简称 RTPSMsgReader,对应的就是wlp的mp_builtinReader属性)两个节点。

1.1WLP时序图

sequenceDiagram
participant BuiltinProtocols
		Participant WLP
		Participant LivelinessManager
		participant RTPSParticipantImpl
		participant StatefulWriter
		Participant StatefulReader
		participant NetworkFactory
		participant UDPTransportInterface
		participant UDPSenderResource
		BuiltinProtocols ->> BuiltinProtocols: 1.initBuiltinProtocols()
		BuiltinProtocols ->> WLP: 2.new wlp
		BuiltinProtocols ->> WLP: 3.initWL
		WLP ->> LivelinessManager: 4.new LivelinessManager
		WLP ->> WLP: 5.createEndpoints
		WLP ->> RTPSParticipantImpl: 6.createWriter()
		RTPSParticipantImpl->> RTPSParticipantImpl: 7.create_writer()
		RTPSParticipantImpl ->> StatefulWriter: 8.new 
		RTPSParticipantImpl->> RTPSParticipantImpl: 9.createSendResources()
		RTPSParticipantImpl->>NetworkFactory: 10.build_send_resources()
		NetworkFactory->>UDPTransportInterface: 11.OpenOutputChannel()
		UDPTransportInterface->>UDPTransportInterface: 12.OpenAndBindUnicastOutputsocket()
		UDPTransportInterface->>UDPSenderResource: 13.new UDPSenderResource()
		RTPSParticipantImpl->> RTPSParticipantImpl: 14.createAndAssociateReceiverswithEndpoint()
		RTPSParticipantImpl->>WLP: return statefulWriter
		WLP ->> RTPSParticipantImpl: 15.createReader()
		RTPSParticipantImpl ->> RTPSParticipantImpl: 16.create_reader()
		RTPSParticipantImpl ->> StatefulReader: 17.new 
		RTPSParticipantImpl->>NetworkFactory: 18.build_send_resources()
		NetworkFactory->>UDPTransportInterface: 19.OpenOutputChannel()
		UDPTransportInterface->>UDPTransportInterface: 20.OpenAndBindUnicastOutputsocket()
		UDPTransportInterface->>UDPSenderResource: 21.new UDPSenderResource()
		RTPSParticipantImpl->> RTPSParticipantImpl: 22.createAndAssociateReceiverswithEndpoint()
		RTPSParticipantImpl->>WLP: return statefulReader

1.BuiltinProtocols 调用initBuiltinProtocols()

2.initBuiltinProtocols() new 了一个wlp

3.wlp调用initWL

主要干了3件事

创建了pub_liveliness_manager_ 见4

创建了sub_liveliness_manager_ 见4

调用WLP::createEndpoints 创建 reader 和writer 见5

4.new LivelinessManager

5.WLP::createEndpoints

创建了StatefulWriter 见6 StatefulReade 见15

6-14.创建 StatefulWriter 可以看一下 之前创建StatefulWriter章节内容,比较类似

15-22.创建Statefulreader 可以看一下 之前创建Statefulreader章节内容,比较类似

1.2WLP源码

 WLP::WLP(
         BuiltinProtocols* p)
   -----省略部分代码
 {
   -----省略部分代码    
     automatic_instance_handle_.value[15] = AUTOMATIC_LIVELINESS_QOS + 0x01;
     manual_by_participant_instance_handle_.value[15] = MANUAL_BY_PARTICIPANT_LIVELINESS_QOS + 0x01;
 }

这里面有两个关键参数 AUTOMATIC_LIVELINESS_QOS 和 MANUAL_BY_PARTICIPANT_LIVELINESS_QOS。

livelinessqospolicy的参数配置

 typedef enum LivelinessQosPolicyKind : fastrtps::rtps::octet
 {
     /**
      * The infrastructure will automatically signal liveliness for the DataWriters at least as often as required by the lease_duration.
      */
     AUTOMATIC_LIVELINESS_QOS,
     /**
      * The Service will assume that as long as at least one Entity within the DomainParticipant has asserted its liveliness the other
      * Entities in that same DomainParticipant are also alive.
      */
     MANUAL_BY_PARTICIPANT_LIVELINESS_QOS,
     /**
      * The Service will only assume liveliness of the DataWriter if the application has asserted liveliness of that DataWriter itself.
      */
     MANUAL_BY_TOPIC_LIVELINESS_QOS
 ​
 } LivelinessQosPolicyKind;

AUTOMATIC_LIVELINESS_QOS 自动的通过DataWriter发送liveliness的消息,发送的间隔小于lease_duration,消息通过WLP的端点发送

MANUAL_BY_PARTICIPANT_LIVELINESS_QOS 如果一个PARTICIPANT包含1个或者多个DataWriter,有这个qos,则participant会发送liveness的消息,这个也是通过wlp 的端点发送

AUTOMATIC_LIVELINESS_QOS 和 MANUAL_BY_PARTICIPANT_LIVELINESS_QOS 可以同时运行,就是说这两类liveliness消息,是分别发送的。

比如一个participant 有一个writer 有AUTOMATIC_LIVELINESS_QOS 这个qos,另一个writer有MANUAL_BY_PARTICIPANT_LIVELINESS_QOS这个qos,那么会有2个liveness的消息周期性的发送。

MANUAL_BY_TOPIC_LIVELINESS_QOS 这个并不由WLP 发送,这个是由writer 发送hearbeat message,heartbeat message中将final flag 和 liveliness的flag 设置一下

Livelinessqos 一般设置3个参数,

kind 类型,就是上面介绍的三个类型,默认一般是AUTOMATIC_LIVELINESS

lease_duration,这个一般是无限大,

announcement_period,就是发送周期,这个一般< 0.7*lease_duration

默认的话,lease_duration,这个一般是无限大,其实就是liveliness qos不会开启

LivelinessQosPolicy 类有三个参数

 //! Liveliness kind <br> By default, AUTOMATIC_LIVELINESS.
     LivelinessQosPolicyKind kind;
     /*! Period within which liveliness should be asserted.
      * On a DataWriter it represents the period it commits to signal its liveliness.
      * On a DataReader it represents the period without assertion after which a DataWriter is considered
      * inactive.
      * By default, c_TimeInfinite.
      */
     fastrtps::Duration_t lease_duration;
     /*! The period for automatic assertion of liveliness.
      * Only used for DataWriters with AUTOMATIC liveliness.
      * By default, c_TimeInfinite.
      *
      * @warning When not infinite, must be < lease_duration, and it is advisable to be less than 0.7*lease_duration.
      */
     fastrtps::Duration_t announcement_period;

这是3个关键参数 kind 执行什么策略,lease_duration这个是多长时间一个writer 需要发送消息来告知其他节点,writer还存在。超过这个时间没有收到消息,表示writer已经下线了。announcement_period表示发送消息的周期,多长时间需要有消息发出来。

这里先对这些参数做个简单的介绍,具体如何运行之后详细深入研究。

步骤3:

 bool WLP::initWL(
         RTPSParticipantImpl* p)
 {
     EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Initializing Liveliness Protocol");
 ​
     mp_participant = p;
 ​
     pub_liveliness_manager_ = new LivelinessManager(
        [&](const GUID_t& guid,
         const LivelinessQosPolicyKind& kind,
         const Duration_t& lease_duration,
         int alive_count,
         int not_alive_count) -> void
        {
           //这个是到livelinessmanager 中TimedEvent被触发的callback
             pub_liveliness_changed(
                 guid,
                 kind,
                 lease_duration,
                 alive_count,
                 not_alive_count);
        },
         mp_participant->getEventResource(),
         false);
 ​
     sub_liveliness_manager_ = new LivelinessManager(
        [&](const GUID_t& guid,
         const LivelinessQosPolicyKind& kind,
         const Duration_t& lease_duration,
         int alive_count,
         int not_alive_count) -> void
        {
             sub_liveliness_changed(
                 guid,
                 kind,
                 lease_duration,
                 alive_count,
                 not_alive_count);
        },
         mp_participant->getEventResource());
 ​
     bool retVal = createEndpoints();
 #if HAVE_SECURITY
     if (retVal && p->is_secure())
    {
         retVal = createSecureEndpoints();
    }
 #endif // if HAVE_SECURITY
     return retVal;
 }

//主要干了三件事

1.创建了pub_liveliness_manager_ 主要是管理本地的writer

2.创建了sub_liveliness_manager_ 主要是管理remote 的writer

3.创建了Endpoints 就是wlp的 writer 和 reader

步骤4:

 LivelinessManager::LivelinessManager(
         const LivelinessCallback& callback,
         ResourceEvent& service,
         bool manage_automatic)
    : callback_(callback)
    , manage_automatic_(manage_automatic)
    , writers_()
    , mutex_()
    , col_mutex_()
    , timer_owner_(nullptr)
    , timer_(
         service,
        [this]() -> bool
        {
             return timer_expired();
        },
         0)
 {
 }

这里初始化了一个TimedEvent,在这个TimedEvent:timer_ 触发的时候(就是lose liveness 的时候)会调用 timer_expired函数

 bool LivelinessManager::timer_expired()
 {
     std::unique_lock<std::mutex> lock(mutex_);
 ​
     if (timer_owner_ == nullptr)
    {
         EPROSIMA_LOG_ERROR(RTPS_WRITER, "Liveliness timer expired but there is no writer");
         return false;
    }
     else
    {
         timer_owner_->status = LivelinessData::WriterStatus::NOT_ALIVE;
    }
 ​
     auto guid = timer_owner_->guid;
     auto kind = timer_owner_->kind;
     auto lease_duration = timer_owner_->lease_duration;
 ​
     lock.unlock();
 ​
     if (callback_ != nullptr)
    {
         callback_(guid, kind, lease_duration, -11);
    }
 ​
     if (calculate_next())
    {
         lock.lock();
 ​
         if ( timer_owner_ != nullptr)
        {
             // Some times the interval could be negative if a writer expired during the call to this function
             // Once in this situation there is not much we can do but let asio timers expire inmediately
             auto interval = timer_owner_->time - steady_clock::now();
             timer_.update_interval_millisec((double)duration_cast<milliseconds>(interval).count());
 ​
             return true;
        }
    }
 ​
     return false;
 }

主要干了2件事

1.调用callback_在这儿就是 WLP::pub_liveliness_changed, 这个函数统计lossliveliness 的次数,回调告知上层应用lossliveliness

2.选出最近会lossliveliness的writer,重新设置timer,如此循环往复

步骤5:

createEndpoints 就是创建WLP的Writer 和 Reader

 bool WLP::createEndpoints()
 {
     const RTPSParticipantAttributes& pattr = mp_participant->getRTPSParticipantAttributes();
     const ResourceLimitedContainerConfig& participants_allocation = pattr.allocation.participants;
 ​
     // Built-in writer history
     HistoryAttributes hatt;
     set_builtin_writer_history_attributes(hatt, false);
     mp_builtinWriterHistory = new WriterHistory(hatt);
 ​
     PoolConfig writer_pool_cfg = PoolConfig::from_history_attributes(hatt);
     payload_pool_ = TopicPayloadPoolRegistry::get("DCPSParticipantMessage", writer_pool_cfg);
     payload_pool_->reserve_history(writer_pool_cfg, false);
 ​
     // Built-in writer
     WriterAttributes watt;
     watt.endpoint.unicastLocatorList = mp_builtinProtocols->m_metatrafficUnicastLocatorList;
     watt.endpoint.multicastLocatorList = mp_builtinProtocols->m_metatrafficMulticastLocatorList;
     watt.endpoint.external_unicast_locators = mp_builtinProtocols->m_att.metatraffic_external_unicast_locators;
     watt.endpoint.ignore_non_matching_locators = pattr.ignore_non_matching_locators;
     watt.endpoint.remoteLocatorList = mp_builtinProtocols->m_initialPeersList;
     watt.matched_readers_allocation = participants_allocation;
     watt.endpoint.topicKind = WITH_KEY;
     watt.endpoint.durabilityKind = TRANSIENT_LOCAL;
     watt.endpoint.reliabilityKind = RELIABLE;
     RTPSWriter* wout;
     if (mp_participant->createWriter(
                 &wout,
                 watt,
                 payload_pool_,
                 mp_builtinWriterHistory,
                 nullptr,
                 c_EntityId_WriterLiveliness,
                 true))
    {
         mp_builtinWriter = dynamic_cast<StatefulWriter*>(wout);
         EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Builtin Liveliness Writer created");
    }
     else
    {
         EPROSIMA_LOG_ERROR(RTPS_LIVELINESS, "Liveliness Writer Creation failed ");
         delete(mp_builtinWriterHistory);
         mp_builtinWriterHistory = nullptr;
         payload_pool_->release_history(writer_pool_cfg, false);
         return false;
    }
 ​
     // Built-in reader history
     set_builtin_reader_history_attributes(hatt, participants_allocation, false);
     mp_builtinReaderHistory = new ReaderHistory(hatt);
 ​
     PoolConfig reader_pool_cfg = PoolConfig::from_history_attributes(hatt);
     payload_pool_->reserve_history(reader_pool_cfg, true);
 ​
     // WLP listener
 ​
     mp_listener = new WLPListener(this);
 ​
     // Built-in reader
 ​
     ReaderAttributes ratt;
     ratt.endpoint.topicKind = WITH_KEY;
     ratt.endpoint.durabilityKind = TRANSIENT_LOCAL;
     ratt.endpoint.reliabilityKind = RELIABLE;
     ratt.expectsInlineQos = true;
     ratt.endpoint.unicastLocatorList =  mp_builtinProtocols->m_metatrafficUnicastLocatorList;
     ratt.endpoint.multicastLocatorList = mp_builtinProtocols->m_metatrafficMulticastLocatorList;
     ratt.endpoint.external_unicast_locators = mp_builtinProtocols->m_att.metatraffic_external_unicast_locators;
     ratt.endpoint.ignore_non_matching_locators = pattr.ignore_non_matching_locators;
     ratt.endpoint.remoteLocatorList = mp_builtinProtocols->m_initialPeersList;
     ratt.matched_writers_allocation = participants_allocation;
     ratt.endpoint.topicKind = WITH_KEY;
     RTPSReader* rout;
     if (mp_participant->createReader(
                 &rout,
                 ratt,
                 payload_pool_,
                 mp_builtinReaderHistory,
                (ReaderListener*)mp_listener,
                 c_EntityId_ReaderLiveliness,
                 true))
    {
         mp_builtinReader = dynamic_cast<StatefulReader*>(rout);
         EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Builtin Liveliness Reader created");
    }
     else
    {
         EPROSIMA_LOG_ERROR(RTPS_LIVELINESS, "Liveliness Reader Creation failed.");
         delete(mp_builtinReaderHistory);
         mp_builtinReaderHistory = nullptr;
         delete(mp_listener);
         mp_listener = nullptr;
         payload_pool_->release_history(reader_pool_cfg, true);
         return false;
    }
 ​
     return true;
 }
 ​

上面函数配置参数创建 mp_builtinReader 和 mp_builtinWriter也就是WLP的Writer 和Reader

1.3类图

classDiagram
WLP *-- StatefulWriter
      WLP *-- StatefulReader
      WLP *-- LivelinessManager
      WLP *-- TimedEvent
      
      class WLP {
          +StatefulWriter mp_builtinWriter
          +StatefulReader mp_builtinReader
          +LivelinessManager pub_liveliness_manager
          +LivelinessManager sub_liveliness_manager
          +TimedEvent manual_liveliness_assertion
          +TimedEvent automatic_liveliness_assertion
      }
      
      class StatefulReader {
      		
      }
      class StatefulWriter {
      }
      class LivelinessManager {
      }
      class TimedEvent {
      }

WLP 主要功能是两个:

1.一个是定期发送消息,这个automatic_liveliness_assertion 和 manual_liveliness_assertion 负责

这是WLP两个关键的TimedEvent

automatic_liveliness_assertion 对应的 LivelinessQosPolicyKind 是 AUTOMATIC_LIVELINESS_QOS ,定期通过wlp的StatefulWriter类型的mp_builtinWriter发送Liveliness的消息。

manual_liveliness_assertion 对应的 LivelinessQosPolicyKind 是 MANUAL_BY_PARTICIPANT_LIVELINESS_QOS,定期通过wlp的StatefulWriter类型的mp_builtinWriter发送Liveliness的消息。

这两类消息类型是不一样的,在发送端是完全无关的。

2.检查和管理writer的状态。这个由pub_liveliness_manager_ 和sub_liveliness_manager_ 来负责,当发现writer 失去liveliness的时候通过回调函数通知上层应用。timer_ 就负责这个事情。

pub_liveliness_manager 这个是participant 内部 writer状态的管理者 sub_liveliness_manager 这个是participant 匹配的远端 writer状态的管理者

2.TypeLookupManager

2.1简介

TypeLookupManager 其实是为了动态类型而准备的一个对象,是可配置的。

我们如果在收发两端都约定好了数据类型,那么不需要TypeLookupManager。我们发送和接收消息的时候需要这个数据类型用来序列化和反序列化消息。

如果我们并没有约定好数据类型,需要TypeLookupManager来传递类型信息。

一般情况下我们都是使用静态类型,就是收发两端提前约定好了类型。动态类型用的不是太多。所以这个TypeLookupManager是可配置的。默认情况下并不会使用到TypeLookupManager。

2.2时序图

sequenceDiagram
participant BuiltinProtocols
		participant TypeLookupManager
		participant RTPSParticipantImpl
		participant StatefulWriter
		participant StatefulReader

		BuiltinProtocols ->> TypeLookupManager: 1.TypeLookupManager
		BuiltinProtocols ->> TypeLookupManager: 2.init_typelookup_service
		TypeLookupManager ->> TypeLookupManager: 3.create_endpoints
		TypeLookupManager ->> RTPSParticipantImpl: 4.createWriter
		RTPSParticipantImpl ->> RTPSParticipantImpl: 5.create_writer
		RTPSParticipantImpl ->> StatefulWriter: 6.new
		TypeLookupManager ->> RTPSParticipantImpl:7.createReader
		RTPSParticipantImpl ->> RTPSParticipantImpl:8.create_reader
		RTPSParticipantImpl ->> StatefulReader: 9.new
  1. BuiltinProtocols创建TypeLookupManager对象
  2. BuiltinProtocols调用TypeLookupManager 的init_typelookup_service 初始化TypeLookupManager
  3. 在初始化TypeLookupManager 的过程中,create_endpoints,就是创建TypeLookupManager的endpoint,也就是StatefulWriter 和StatefulReader
  4. 在create_endpoints 函数中调用RTPSParticipantImpl 的 create_edp_writer
  5. RTPSParticipantImpl的createWriter函数 调用自己的create_writer函数
  6. 最终new了一个StatefulWriter

7,8,9类似 创建了一个StatefulReader

2.3源码解析

步骤1:new TypeLookupManager

没什么太多内容。

步骤2:init_typelookup_service

 bool TypeLookupManager::init_typelookup_service(
        RTPSParticipantImpl* participant)
 {
    EPROSIMA_LOG_INFO(TYPELOOKUP_SERVICE, "Initializing TypeLookup Service");
    participant_ = participant;
    bool retVal = create_endpoints();
    return retVal;
 }

主要是调用了create_endpoints

步骤3:

 bool TypeLookupManager::create_endpoints()
 {
     const RTPSParticipantAttributes& pattr = participant_->getRTPSParticipantAttributes();
 ​
     // Built-in history attributes.
     ----
     watt.endpoint.reliabilityKind = fastrtps::rtps::RELIABLE;
     watt.endpoint.durabilityKind = fastrtps::rtps::VOLATILE;
 ​
     // Built-in request writer
     if (builtin_protocols_->m_att.typelookup_config.use_client)
    {
         builtin_request_writer_history_ = new WriterHistory(hatt);
 ​
         RTPSWriter* req_writer;
         if (participant_->createWriter(
                     &req_writer,
                     watt,
                     builtin_request_writer_history_,
                     nullptr,
                     fastrtps::rtps::c_EntityId_TypeLookup_request_writer,
                     true))
        {
             builtin_request_writer_ = dynamic_cast<StatefulWriter*>(req_writer);
             EPROSIMA_LOG_INFO(TYPELOOKUP_SERVICE, "Builtin Typelookup request writer created.");
        }
         ------
    }
 ​
     // Built-in reply writer
     if (builtin_protocols_->m_att.typelookup_config.use_server)
    {
         builtin_reply_writer_history_ = new WriterHistory(hatt);
 ​
         RTPSWriter* rep_writer;
         if (participant_->createWriter(
                     &rep_writer,
                     watt,
                     builtin_reply_writer_history_,
                     nullptr,
                     fastrtps::rtps::c_EntityId_TypeLookup_reply_writer,
                     true))
        {
             builtin_reply_writer_ = dynamic_cast<StatefulWriter*>(rep_writer);
             EPROSIMA_LOG_INFO(TYPELOOKUP_SERVICE, "Builtin Typelookup reply writer created.");
        }
         ------
    }
 ​
     ------
     ratt.endpoint.reliabilityKind = fastrtps::rtps::RELIABLE;
     ratt.endpoint.durabilityKind = fastrtps::rtps::VOLATILE;
 ​
     // Built-in request reader
     if (builtin_protocols_->m_att.typelookup_config.use_server)
    {
         request_listener_ = new TypeLookupRequestListener(this);
         builtin_request_reader_history_ = new ReaderHistory(hatt);
 ​
         RTPSReader* req_reader;
         if (participant_->createReader(
                     &req_reader,
                     ratt,
                     builtin_request_reader_history_,
                     request_listener_,
                     fastrtps::rtps::c_EntityId_TypeLookup_request_reader,
                     true))
        {
             builtin_request_reader_ = dynamic_cast<StatefulReader*>(req_reader);
             EPROSIMA_LOG_INFO(TYPELOOKUP_SERVICE, "Builtin Typelookup request reader created.");
        }
         -----
    }
 ​
     // Built-in reply reader
     if (builtin_protocols_->m_att.typelookup_config.use_client)
    {
         reply_listener_ = new TypeLookupReplyListener(this);
         builtin_reply_reader_history_ = new ReaderHistory(hatt);
 ​
         RTPSReader* rep_reader;
         if (participant_->createReader(
                     &rep_reader,
                     ratt,
                     builtin_reply_reader_history_,
                     reply_listener_,
                     fastrtps::rtps::c_EntityId_TypeLookup_reply_reader,
                     true))
        {
             builtin_reply_reader_ = dynamic_cast<StatefulReader*>(rep_reader);
             EPROSIMA_LOG_INFO(TYPELOOKUP_SERVICE, "Builtin Typelookup reply reader created.");
        }
         ------
    }
 ​
     return true;
 }
 ​

主要是创建了1个writer,1个reader

TypeLookupManager 可以配置为client或者server

配置为client的话,会创建 一个Request_Writer和一个Reply_Reader,

配置为server的话,会创建一个Request_Reader和一个Reply_Writer。

2.4类图

classDiagram
 TypeLookupManager *-- StatefulWriter
      TypeLookupManager *-- StatefulReader
      
      class TypeLookupManager {
          +StatefulWriter builtin_request_writer_
          +StatefulWriter builtin_reply_writer_
          +StatefulReader builtin_reply_reader_
          +StatefulReader builtin_request_reader_
      }
      
      class StatefulReader {
      		
      }
      class StatefulWriter {
      }

TypeLookupManager如果配置为client的话,会创建 一个Request_Writer和一个Reply_Reader,如果配置为server的话,会创建一个Request_Reader和一个Reply_Writer。

classDiagram
RTPSParticipantImpl *-- BuiltinProtocols
      BuiltinProtocols *-- PDP
      PDP *-- RTPSWriter
      PDP *-- RTPSReader
      BuiltinProtocols *-- WLP
      PDP *-- EDP
      EDP <-- EDPSimple
      EDPSimple *--StatefulWriter
      EDPSimple *--StatefulReader
      BuiltinProtocols *-- TypeLookupManager
      class RTPSParticipantImpl {
          +BuiltinProtocols mp_builtinProtocols
      }
      class BuiltinProtocols {
      		+PDP mp_PDP
      		+WLP mp_WLP
      		+TypeLookupManager tlm_
      }
      class PDP {
      		+EDP mp_EDP
      }
      class RTPSWriter {
      }
      class RTPSReader {
      }
      class EDPSimple {
      		std::pair<StatefulWriter*,WriterHistory*> publications_writer_
      		std::pair<StatefulWriter*,WriterHistory*> subscriptions_writer_
      		std::pair<StatefulReader*,ReaderHistory*> publications_reader_
      		std::pair<StatefulReader*,ReaderHistory*> subscriptions_reader_
      }

这是完整的BuiltinProtocols的类图,主要包含 PDP EDP WLP TypeLookupManager,他们都有自己的RTPSWriter 和 RTPSReader

总结:这一篇主要介绍WLP 和 TypeLookupManager 我们通过3篇博客,把内置协议都介绍了一下。

下面两篇介绍一下fastdds 中两个关键的对象 TimedEvent 和 Message

目录:

第一篇 一个例子

车载消息中间件FastDDS 源码解析(一)FastDDS 介绍和使用

第二篇fastdds的组成

车载消息中间件FastDDS 源码解析(二)RtpsParticipant的创建(上)

车载消息中间件FastDDS 源码解析(三)RtpsParticipant的创建(中)

车载消息中间件FastDDS 源码解析(四)RtpsParticipant的创建(下)

车载消息中间件FastDDS 源码解析(五)BuiltinProtocols(上)

车载消息中间件FastDDS 源码解析(六)BuiltinProtocols(中)EDP

车载消息中间件FastDDS 源码解析(七)BuiltinProtocols(下)WLP&TypeLookupManager

车载消息中间件FastDDS 源码解析(八)TimedEvent

车载消息中间件FastDDS 源码解析(九)Message

第三篇组网建立连接

pdp建连

车载消息中间件FastDDS 源码解析(十)发送第一条PDP消息(上)

FastDDS 源码解析(十一)发送第一条PDP消息(中)

FastDDS 源码解析(十二)发送第一条PDP消息(下)---异步发送

FastDDS 源码解析(十三)发送第一条PDP消息---跨进程发送

FastDDS 源码解析(十四)接收PDP消息(上)

FastDDS 源码解析(十五)接收PDP消息(下)

FastDDS 源码解析(十六)处理PDP消息——PDP匹配

EDP建连

FastDDS 源码解析(十七)处理PDP消息——EDP匹配

FastDDS 源码解析(十八)EDP阶段发送心跳heartbeat

FastDDS 源码解析(十九)EDP阶段处理heartbeat消息,发送acknack消息

FastDDS 源码解析(二十)处理acknack消息