XRCE-DDS协议分析

对XRCEDDS协议的阅读理解和分析

关于睡眠周期的相关问题

嵌入式设备,尤其是资源受限的嵌入式设备一般都会有能耗管理的相关模块,可以让设备在空闲或等待状态时进入睡眠模式来减少能耗。XRCE-DDS声称对具有睡眠周期的嵌入式设备有很好的考虑,这里了细致对specification进行分析看都有哪些举措。

检索specification中跟sleep相关的语句,发现协议出现sleep有15处,总结有7处谈及对睡眠周期的处理,下述是详细的列举和介绍。

  • Scope中的概述和XRCE Object Model中General

The XRCE protocol is a client-server protocol between resource-constrained devices (clients) and an XRCE Agent (server). The protocol allows the resource constrained devices with sleep/wake cycles to have access to the DDS Global Data Space over limited-bandwidth networks.

​ 这里就是协议的第一章节以及对象模型的概述章节,点明了该协议是一个资源受限设备和代理之间的客户端-服务器协议。该协议允许拥有睡眠/清醒周期的资源受限设备在受限带宽网络上拥有访问DDS全局数据空间的能力

  • XRCE Client一节中对XRCE-DDS规范中的XRCE Object Model不同于DDS Object Model的三个原因描述的第二条

···

  1. The XRCE Client connectivity is assumed to be inherently intermittent due to potentially aggressive use of lowpower mode and deep sleep to conserve battery or loss of radio connectivity. The DDS-XRCE DDS Object Model must overcome intermittent connectivity by introducing a “session,” which can exist across repeated sleep-wakeup cycles by a device.

···

​ 这里是介绍XRCE对象模型的第二小节XRCE Client处的一个原因解释,主要是区分DDS对象模型。这里XRCE Client的链接被认为本质是间歇性的,主要是因为有可能很积极的使用低功耗模式或者深度睡眠来节省电池,或者说是因为无线电链接的经常丢失。所以提到该对象模型引入了session来克服间歇性链接,且session可存在于设备的重复睡眠唤醒周期中的

​ 这里非常重要,首先介绍了Client中一个非常重要的概念session的定义的原因和用途,就是为了克服间歇性链接,其次强调session可以在睡眠唤醒周期中存在,这一点似乎对我们建模非常重要,然后就是介绍了间歇性链接产生的原因,是很合理的。

  • 介绍read操作所携带的参数的定义,有一个参数叫做min_pace_period

The setting of the min_pace_period configures the minimum interval in milliseconds between the sample messages sent from the Agent to the Client. This period makes it possible for the client to go into a sleep cycle between messages.

​ 这里是在介绍XRCE DataReader对象模型的read操作时,对其一个名为min_pace_period的参数的介绍,顾名思义,这个参数是控制从Agent发往Client端的多个消息间的最小时间间隔的。这个时间间隔使得Client可以在消息接收间也可以进入一个睡眠状态。

​ 也就是说,Client有可能的睡眠周期发生的时间,就是在定期接收Agent发来的消息之间。这是一种命令Agent控制消息发送频率的手段。我们在建立模型时,可以考虑将睡眠周期放在这里?

  • XRCE Protocol的概述部分,介绍该协议主要为了解决哪些设备带来的挑战,其中第二条、第七条、第12条和第13条有所涉及

​ ·······

  • Work with devices that undergo sleep cycles. These devices may be active once every few minutes, days, months, or even years.

​ ······

  • Support receiving information both reliably and in a best effort manner, even if the information was sent while the Client was undergoing a sleep cycle.

​ ······

  • Cannot operate without infrastructure support. They need an XRCE Agent to be reachable to them. This is a necessary consequence of the need for XRCE Clients to undergo deep sleep cycles.
  • Do not communicate directly peer-to-peer. All communications are brokered (relayed) by one or more DDSXRCE Agents. This is also a necessary consequence of the need for Clients to undergo deep sleep cycles.

​ 其中第2条只是一个简单的陈述,就是设备具有睡眠周期,可能只会隔几分钟、几天、几个月甚至几年才是活跃的。第7条表示协议应该支持Best Effort方式的信息传输,即便是针对睡眠周期内的client。第12条则是强调XRCE Agent的重要性,表明因为Client会进入睡眠周期,所以必须要靠Agent来访问Client。第13条则是在否定直接的P2P通信,依然是强调所有的通信都应该依靠Agent实现,因为Client可能会进入睡眠周期中。

​ 这个其实主要只是一个概述,给我们带来的有价值的东西不是很多,但有3点需要注意,第一点是睡眠周期应该是可长可短的,第二点是如果我们采用BestEffort方式进行消息传输,似乎不需要考虑Client是否处于睡眠周期内,第三点就是P2P通信无疑对于有睡眠周期的设备来说是不现实的。

  • 介绍READ_DATA这一submessage的部分,重申了read操作的作用

The read operation also allows an XRCE Client to control when data may be sent by the XRCE Agent so that the Agent does not unnecessarily wake up the Client during its sleep cycle

​ read操作可以允许一个XRCE Client来控制由Agent发送的数据何时被送达,这样Agent就不会将Client从睡眠周期中进行唤醒

​ 注意这里的表述似乎在说Agent的消息可以将Client从睡眠周期中唤醒,但是那是不被希望的。这能否为我们的模型带来一些有趣的东西呢?

  • 介绍ACKNACK这一submessage的部分。

The ACKNACK submessage is used to enable a transport independent reliability protocol to be implemented. If the transport used for a session is able to reliably send messages in case of disconnection or a wakeup/sleep cycle then these messages may not be required.

This specification does not dictate whether ACKNACK messages shall be sent only in response to HEARTBEAT. messages or can also be sent whenever one side detects message loss. However, in general it is expected that it is the XRCE Client that initiates any synchronization, and therefore,the XRCE Agent will only send ACKNACK messages in response to HEARTBEAT messages. This is because an XRCE Client may not be continually available as it goes on sleep cycles.

​ ACKNACK 子消息被用来实现一个独立于可靠协议的传输实现,如果session代表的传输能够在断开连接或者一个清醒睡眠周期中保持可靠的话,这个消息可能就不需要了。

​ 规范并没有表明ACKNACK消息是应该作为HEARTBEAT消息的响应被发送,还是在无论何时任何一边发现消息丢失后就被发送。通常情况下,应该有XRCE Client来发起任何的同步,因此,XRCE Agent将仅仅在回应HEARTBEAT消息时发送ACKNACK,因为XRCE Client在进入睡眠周期后可能是不可持续使用的。

​ 第一段话其实表明了XRCE-DDS在不可靠通信协议的基础上,实现的可靠的一种手段,即ACKNACK子消息。所以也表明如果有一个可靠的底层协议可以满足断开连接以及睡眠情况下的可靠传输的话,ACKNACK子消息不是必要的。

​ 第二段话则是阐明了重点,首先是ACKNACK发送的两种情景,一种是仅仅作为HEARTBEAT的回应,另一种是发现消息丢失后告知对方。根据后面的描述,对于XRCE Agent来说,为了防止在Client睡眠期间持续发送ACKNACK造成不必要唤醒或者说不必要的持续发送,仅仅适用于第一种情景,而对于XRCE Client来说,尽管协议里没有明确指出,但应该是在大多数情况下,周期性的检查消息是否丢失,丢失后立即告知对方。

​ (PS:这里其实如果考虑细节非常头疼,就是对于XRCE Client来说,是应该在每收到一个消息就检测是否是丢失消息呢?还是应该有一个区间,允许乱序发送呢?但是结合specification中好像有介绍按序接收,但是按序接收会不会是指上层对消息进行的重组呢?总之就非常头疼。)

  • 介绍HEARTBEAT这一submessage的部分

This specification does not limit a session to use a particular type of transport. If a session transport is able to reliably send messages in case of disconnection or a wakeup/sleep cycle then these messages may not be required.

This specification does not dictate the timing of HEARTBEAT messages. However, in general it is expected that it is the XRCE Agent will only send HEARTBEAT messages when it has some indication that the XRCE Client is active and not in a sleep cycle. This is to avoid awakening the XRCE Client unnecessarily.

​ 规范并没有限制一个session使用一个特定类型的传输。如果一个session的传输可以在断开连接或者清醒睡眠周期的条件下可靠地发送消息,那么HEARTBEAT也是不需要的。

​ 规范也并没有表明HEARTBEAT消息的时间,通常来说希望Agent可以在得知XRCE Client是活跃的时候发送心跳消息,这是为了避免不必要的唤醒XRCE Client。

​ 第一点没什么好解释的,跟ACKNACK相同,因为两者本来就是一对的。第二点可能就就需要我们考虑HEARTBEAT是否应该在XRCE Agent 和 XRCE Client端有不同的建模方式

  • client应用间的直接P2P通信

An additional drawback of the direct peer to peer communication is that the applications cannot easily go into sleep cycles as the XRCE Agents they contain need to be active in order to process the messages from the XRCE Clients. Therefore, is not suitable for many resource-constrained scenarios.

​ 直接的P2P通信的额外缺点是应用不能轻易进入睡眠周期,因为它们包含的XRCE代理需要保持活跃状态才可以处理XRCE CLients的消息,所以不适用于资源受限的环境。

​ 大意就是分析了P2P通信在资源受限设备的不可行性。

对于时间相关的注意

Read消息中含有ReadSpecification消息,该消息中含有一个结构体名为DataDeliveryControl,用来传输控制,其中包括了最大经过时间、最小传输间隙(min_pace_period)、每秒钟最大传输字节数(max_bytes_per_sec)以及最大消息数(max_sample)。其中最大经过时间(max_elapsed_time)表示将读取操作配置为在从进行读取操作的那一刻起经过指定的时间后终止。为0时表示没有最大值。

client_representation消息中含有client_timestamp,应该是用来指示ProxyClient当前Client的时间。agent_representation同理。两者通过这两个时间戳来进行时间同步。

如果存在continuous_read_options 成员,则代理应多次调用读取操作。 调用周期不能快于pace_period。 因此,返回的数据可能包含将来到达 DDS DataReader 的数据。 一旦 max_total_samples 已返回,或 max_total_elapsed_time 已过,代理应停止调用读取操作。

整体模型框架

整体来说我们的系统就是一个由Client、Agent和Session、Stream以及Message组成的系统。

client和Agent通过一次握手建立链接,通过此链接,可以初始化形成session。

根据session本身默认的可靠stream流,发送create_client子消息,就可以在Agent处创建或重用ProxyClient

确认Agent处ProxyClient的存在后,就可以使用create子消息,利用ProxyClient来创建各种实体资源,包括Participate、Topic、Publisher\Subscriber、DataWriter\DataReader。

完成配置(包括预配置和自行配置)的客户端,可以进行收发消息。通过ClientKey来标识所要使用的ProxyClient,通过DataWriter或者DataReader来进行读写消息。

建模思考

关于Channel与消息类型

打算Client与Stream、Stream与Agent交互之间使用msg变量,使用的channel是write_msg和read_msg

msg变量内部存在很多submsg,Agent到Root、ProxyClient由若干个不同的channel传递不同的变量,比如create_client、create、writedata、readdata