# ReliabilityQoS

# 功能介绍

对各种主题的数据设置传输模式,分为可靠的传输和尽力而为的传输。可靠传输能保证写者发出的数据不丢失,不乱序。尽力而为的传输则可以保证写者能以最快速度发送数据,但有可能会丢失部分数据包。

以下为 ReliabilityQoS 的 kind 属性能设置的值:

DDS_BEST_EFFORT_RELIABILITY_QOS:可靠的传输。发布端写者在发出数据之后中间件会判断订阅端读者是否成功收到数据。若订阅端没有收到,中间件会通知发布端,发布端的写者就会再发一次订阅端没收到的数据,保证订阅端能收到。在稳定状态下(写者不会再写新的数据),中间件会保证写者的历史记录所有数据能够全部发送给读者。但在写者会发送新数据的情况下,就需要对 History 进行设置,确定写者发送的数据样本哪些作为历史记录保存,哪些需要从历史记录丢弃。

DDS_BEST_EFFORT_RELIABILITY_QOS:尽力而为的传输。发布端写者在发送数据的时候不会关注订阅端读者是否接受到数据,写者不会因为读者漏接某个数据而再发送一次漏接的数据,依然会继续发送接下来的数据。一般用于更新速率很快,丢失少许数据无碍的情况。是 DataReaders 和 Topics 的默认值。

# 兼容性

开启服务后,DDS 服务会对写者和读者的 ReliabilityQoS 的 kind 值进行比对检查。首先对于 DDS 服务来说,该 QoS 的 Kind 值是有序的。Kind 的大小顺序如下所示:

DDS_BEST_EFFORT_RELIABILITY_QOS < DDS_RELIABLE_RELIABILITY_QOS。

当写者的 ReliabilityQoS 的 Kind 值大于或等于读者的 ReliabilityQoS 的 Kind,DDS 才会认为写者和读者的状态是兼容的。

比如写者的 kind 为 DDS_BEST_EFFORT_RELIABILITY_QOS,而读者的 kind 为 DDS_RELIABLE_RELIABILITY_QOS。根据 QoS 的 kind 大小顺序,则写者的 kind < 读者的 kind。就会导致不兼容,无法通信的情况。

# 使用方法

ReliabilityQoS 成员列表如下表。

表 1 ReliabilityQoS 成员列表及 HistoryQoS 成员列表
类型 字段名 描述
Reliability- QoS- PolicyKind Kind DDS_BEST_EFFORT_RELIABILITY_QOS:尽力而为的传输。DDS 数据样本发送一次,允许部分样本接收端没有收到。 DDS_RELIABLEE_RELIABILITY_QOS:DDS 将确保接收端收到发送的数据,若出现样本丢失的情况,会重新发送丢失的 DDS 样本

若 ReliabilityQoS.kind 的值为 DDS_RELIABLEE_RELIABILITY_QOS,则还需要对 HistoryQoS 进行设置。

# DataWrietr 端

1) QoS 赋值

对 DDS_DataWriterQoS 数据类型的变量 wQoS 下的 reliability 的 kind 属性进行赋值。若 kind 的值为 DDS_RELIABLEE_RELIABILITY_QOS,则还需要对 wQoS.history 进行赋值。最后 wQoS 在写者创建的时候作为参数传入 create_datawriter。

图 1 DataWriter 的 ReliabilityQoS 赋值

# DataReader 端

1) QoS 赋值

对 DDS_DataReadrQoS 数据类型的变量 rQoS 下的的 reliability 的 kind 属性进行赋值。若 kind 的值为 DDS_RELIABLEE_RELIABILITY_QOS,则还需要对 wQoS.history 进行赋值。

若 kind 的值为 DDS_RELIABLEE_RELIABILITY_QOS,也可以对 HistoryQoS 的 depth 进行设置。当接受数据方式设置为读取样本列表(read)的时候,每次读取数据就会读取 depth 个数的最新数据。而接受方式设置为 take 的时候,每次读取只会读最新的一个数据。

然后将 QoS 作为参数传入 create_datawriter()。

图 2 DataReader 的 ReliabilityQoS 赋值
## 效果展示

1) 适用场景

该 QoS 一般用于设置可靠通信或尽力而为的通信。当每份数据样本都很重要的时候可以选择设置该 QoS 为可靠传输,或者有大量数据,丢失个别数据不影响的时候可以设置为尽力而为的传输方式

2) 使用例子

  • 尽力而为通信(take 读取数据)

下图为尽力而为通信,take 读取数据的结果。可以看出,接收端每次读取数据都是读最新的一个数据。所有不同 ReliabilityQoS 以及 historyQoS 设置的 take 读取数据都是只读最新的一个数据样本。其他的不同设置不再展示效果。

图 3 尽力而为通信(take 读取数据)
- 尽力而为通信(read 读取数据)

下图为尽力而为通信,read 读取数据的结果。可以看出,接收端每次读取数据都是读最新的 5 个数据。代码里 depth 的默认值为 5,如果设置为其他值,那么就会读取最新的其他值个的数据。

图 4 尽力而为通信(read 读取数据)
  • 可靠通信+KEEP_ALL(read 读取数据)

下图为可靠通信,HistoryQoS.kind 设置为 KEEP_ALL,read 读取数据的结果。可以看出,接收端每次读取数据会读取所有的历史以及最新数据样本,无视 depth 的设定。

图 5 可靠通信(read 读取数据)
  • 可靠通信+KEEP_LAST(read 读取数据)

下图为可靠通信,HistoryQoS.kind 设置为 KEEP_LAST,depth 设置为 3,read 读取数据的结果。可以看出,接收端每次读取数据会读 history 缓存大小设置的个数的数据。

图 6 可靠通信+KEEP_LAST(read 读取数据)