Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP

分析EDP交互码流(No.75~No.109)前,先说明下图图3-1码流中各个子消息的功能。

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第1张图片 图3-1 发布端和订阅端匹配完整码流

名称

功能

INFO_TS

指示该条RTPS消息被发送时的时间戳。

INFO_DST

指示在该条RTPS消息中,INFO_DST后面的子消息的处理者RTPS reader实体的GuidPrefix为INFO_DST.GuidPrefix。

DATA(p)

数据消息,包含参与者的属性信息,即PDP消息。

DATA(w)

数据消息,包含userWriter的属性信息。当发布端userWriter创建成功后,该消息会被发送给订阅端。

DATA(r)

数据消息,包含userReader的属性信息。当订阅端userReader创建成功后,该消息会被发送给发布端。

DATA

数据消息,包含用户发送的实际消息内容。

HEARTBEAT

该消息有两个功能:

1.它通知Reader在Writer的历史缓存中可用的序列号,这样Reader就可以请求(使用一个AckNack消息)任何已经错过的内容。

2.它要求Reader发送对已进入Reader历史缓存的CacheChange更改的确认,以便Writer了解Reader的状态。

所有Heartbeat消息都有第一个功能。也就是说,Reader总是会发现writer的HistoryCache的状态,并可能请求它所遗漏的内容。通常,如果它丢失了一个CacheChange,RTPS Reader会发送一个AckNack消息。

Writer使用FinalFlag请求Reader对它收到的序列号发送确认信息。如果Heartbeat设置了FinalFlag,那么Reader就不需要回AckNack消息了。但是,如果没有设置FinalFlag,那么Reader必须发送一个AckNack消息,指示它已经接收到哪些缓存更改,即使AckNack指出它已经在Writer的历史缓存中获得了所有的CacheChange更改。

ACKNACK

该子消息用于将Reader的状态通知Writer。该子消息允许Reader告知Writer所收到的序列号,以及它仍然缺少的序列号。这个子消息可以用来做正常应答以及异常应答。

ACKNACK消息中元素readerSNState,所有在readerSNState.base之前的序列号是已经被Reader确认收到的。出现在集合里面的序列号是Reader没有收到的序列号。

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第2张图片 图3-2 端点消息交互图

图3-2 中的所有的Writer和Reader端点,又分为有状态端点和无状态端点。PDP的2个端点是无状态端点。EDP和WLP的6个端点都是有状态端点,UserWriter和UserReader端点由于在本示例当中Qos设置的是可靠传输,所以他们也是有状态端点。

有状态Writer和Reader建立关联的消息交互如图3-3所示。

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第3张图片 图3-3 StatefulWriter和StatefulReader建立关联消息交互图

图中缩写意义如下:

缩写

含义

HB

HEARTBEAT消息。

ACK

ACKNACK消息。

INIT_ACK

初始化ACKNACK消息。

ACKNACK.readerSNState的bitmapBase和numBits都为0,如图3-4所示。

该消息在StatefulReader匹配一个StatefulWriter的时候被发送。当StatefulWriter收到该消息时,响应HEARTBEAT消息。

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第4张图片 图3-4 初始化ACKNACK消息

图3-3 中5条消息的详细描述如下:

  1. 通过收到对端的PDP消息,Writer获取到对端对应的Reader的属性信息。这时给该Reader发送HEARTBEAT消息。
  2. Reader收到了Writer的HEARTBEAT消息,响应ACKNACK消息。
  3. 当Reader通过PDP消息,获取到了对端对应的Writer的属性信息,这时发送初始化ACKNACK给对端Writer。
  4. Writer收到初始化ACKNACK消息,响应HEARTBEAT消息。
  5. Reader收到HEARTBEAT消息,响应ACKNACK消息。

所以理论上一对StatefulWriter和StatefulReader建立关联会产生5条RTPS消息,其中HEARTBEAT两条,ACKNACK三条。另外,StatefulWriter和StatefulReader建立关联,发送消息的顺序不会严格和图3-3中的一致,和实际测试环境相关。

注意,为什么说是理论上,因为有可能少于5条。图3-3中蓝色的ACKNACK消息,有可能Reader不会发送,原因是Reader接收Writer的HEARTBEAT消息并响应ACKNACK消息的前提是,Reader已经匹配了该Writer,如果在接收到Writer的HEARTBEAT消息时,Reader还没有完成和该Writer的匹配,那么HEARTBEAT消息会被Reader丢弃,同时Reader也不会响应ACKNACK消息。这种情况是存在的,幸运的是本篇博客中截取码流的这次测试,所有有状态端点的交互都没有出现这种情况。笔者测试过多次,实际上这种情况出现的概率很高。

StatefulReader接收到StatefulWriter的HEARTBEAT消息时,判断是否匹配的代码段如下:

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第5张图片
Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第6张图片

EDP和WLP一共6对有状态端点,建立连接理论上会产生30条RTPS消息。HEARTBEAT一共12条,ACKNACK一共18条。

图3-1中,从编号75到编号107的RTPS码流对应的正好是EDP和WLP的6对有状态端点建立连接的码流。一共30条RTPS消息。具体消息数分类如下:

类型

数量

总计

HEARTBEAT

6对* 每对发送2条

12

ACK

6对* 每对发送2条

12(有可能少于12,原因前面已经描述过)

ACK(初始化ACK)

6对* 每对发送1条

6

具体EDP和WLP端点消息交互可以参考图3-4的编号75到107。

图3-5消息交互和图3-1的wireshark码流是对应的。

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第7张图片 图3-5 EDP和WLP端点消息交互图

EDP和WLP的端点都是通过对端发来的PDP消息,获取对端端点的属性信息。然后进行消息交互,建立关联。

EDP和WLP的端点都完成关联了,然后轮到UserWriter和UserReader建立关联。

UserWriter在被创建时,它的属性信息被封装成数据,存放在发布端EDP的SEDPPubWriter的历史缓存中。UserWriter被创建时调用堆栈如下:

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第8张图片

UserReader在被创建时,它的属性信息也被封装成数据,存放在订阅端EDP的SEDPSubWriter的历史缓存中。UserReader被创建时调用堆栈如下: 

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第9张图片

由于SEDPPubWriter和SEDPSubWriter的历史缓存中存在数据,所以在他们同对端Reader端点建立关联的时候,也就是如图3-3建立连接的时候,发布端SEDPPubWriter,通过HEARTBEAT消息告知订阅端SEDPPubReader,自己的历史缓存中有序列号为1的数据(即UserWriter的属性信息)。HEARTBEAT消息如下图: 

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第10张图片

订阅端SEDPPubReader收到HEARTBEAT消息,响应ACKNACK消息,因为没有收到序列号为1的数据,所以在消息内容中标记了该条数据没有被收到。ACKNACK消息如下图: 

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第11张图片

发布端SEDPPubWriter收到ACKNACK消息,启动响应ACKNACK消息的定时器,定时器超时后,发送序列号为1的DATA消息(UserWriter的属性信息)给订阅端SEDPPubReader。对应wireshark码流中编号为108的RTPS消息。DATA消息内容如下: 

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第12张图片

至此,订阅端获取到了发布端的UserWriter的属性信息。

当订阅端SEDPSubWriter和发布端SEDPSubReader如图3-3建立关联时,订阅端SEDPSubWriter发送HEARTBEAT消息告知发布端SEDPSubReader,自己的历史缓存中有序列号为1的数据(即UserReader的属性信息),HEARTBEAT消息如下图:

 

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第13张图片

发布端SEDPSubReader收到HEARTBEAT消息,响应ACKNACK消息,因为没有收到序列号为1的数据,所以在消息内容中标记了该条数据没有被收到。ACKNACK消息如下图: 

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第14张图片

订阅端SEDPSubWriter收到ACKNACK消息,启动响应ACKNACK消息的定时器,定时器超时后,发送序列号为1的DATA消息(UserReader的属性信息)给发布端SEDPSubReader。对应wireshark码流中编号为109的RTPS消息。DATA消息内容如下: 

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第15张图片

至此,发布端获取到了订阅端的UserReader的属性信息,订阅端也获取到了发布端的UserWriter的属性信息。

发布端获取到订阅端的UserReader的属性信息,会检查和本地UserWriter是否匹配,比如TopicName,TypeName,TopicKind,QoS是否匹配,如果匹配,UserWriter开始按照图3-3中Writer的流程发消息,开始建立关联。此时发布端可以开始发送用户数据。

Fast RTPS原理与代码分析(3):动态发现协议之端点发现协议EDP_第16张图片

订阅端获取到发布端的UserWriter的属性信息,会检查和本地UserReader是否匹配,比如TopicName,TypeName,TopicKind,QoS是否匹配,如果匹配,UserReader开始按照图3-3中Reader的流程发消息,开始建立关联。此时订阅端可以收到发布端发送的用户数据。 

你可能感兴趣的:(fastrtps)